Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPCv2 and cbor support #3006

Open
wants to merge 59 commits into
base: version-3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
c4aa004
Initial CBOR work
mullermp Apr 11, 2024
c389458
Remove client spec
mullermp Apr 11, 2024
7157890
Test runner for decode success
mullermp Apr 11, 2024
86b8de0
Add error test runner
mullermp Apr 11, 2024
0b24ecc
Major CBOR refactoring, all tests pass
alextwoods Apr 11, 2024
870d738
Fix error decoder specs
alextwoods Apr 11, 2024
3eac02a
Remove decoder spec, use utc in encoder spec
alextwoods Apr 11, 2024
bf23dbf
Fix time test - use utc
alextwoods Apr 11, 2024
05c4722
Rubocop/style cleanups
alextwoods Apr 12, 2024
029e8f0
Rename spec
alextwoods Apr 12, 2024
885c880
Merge branch 'version-3' into cbor
mullermp Apr 15, 2024
b5d2aab
WIP: protocol tests
mullermp Apr 15, 2024
7f5ff9f
Fix some parts of test runner for rpcv2 + add Time parsing to decoder…
alextwoods Apr 15, 2024
14f2bfa
Add other engine support and untangle error handlers across all proto…
mullermp Apr 15, 2024
5070c61
More refactors and test passing
mullermp Apr 16, 2024
f67973e
More test fixes
mullermp Apr 16, 2024
0b52fa1
Protocol tests pass
mullermp Apr 16, 2024
702d9de
Remove cbor gem
mullermp Apr 16, 2024
daff795
More refactors around cbor half and handlers
mullermp Apr 16, 2024
345024b
Flatten cbor and bring back half
mullermp Apr 16, 2024
5f8c337
Flatten json and xml engines
mullermp Apr 16, 2024
46988ce
Per engine protocol tests
mullermp Apr 16, 2024
6b998e1
Merge branch 'version-3' into cbor
mullermp Apr 16, 2024
824188f
Fix some other spec files
mullermp Apr 16, 2024
ee3c477
Update assert to handle hash values when nil
jterapin Apr 16, 2024
531d2d9
Update test runner to include test ids
jterapin Apr 16, 2024
2d01fae
Merge branch 'version-3' into cbor
mullermp Apr 19, 2024
185f88d
PR feedback
mullermp Apr 19, 2024
e15456f
Fix jruby tests
mullermp Apr 19, 2024
06289c6
Support protocols generation resolution
mullermp Apr 19, 2024
f6185e4
Fix test
mullermp Apr 19, 2024
5d4d732
Fix other test
mullermp Apr 19, 2024
6edddb3
Fix failing tests again
mullermp Apr 19, 2024
bdf3fa6
Merge branch 'version-3' into cbor
mullermp Apr 19, 2024
5e08ccb
Merge branch 'version-3' into cbor
mullermp Apr 21, 2024
a8856e6
Fix json extras tests
mullermp Apr 21, 2024
cec94b1
Fix generating event in event stream with no members
mullermp Apr 21, 2024
2bc4072
Revert "Fix generating event in event stream with no members"
mullermp Apr 21, 2024
cc02a70
Update decode tests
mullermp Apr 29, 2024
3c9166d
Merge branch 'version-3' into cbor
mullermp Apr 29, 2024
e3bf737
Update minimum version
mullermp Apr 29, 2024
0d8f8b0
Try new changelog action
mullermp Apr 29, 2024
a6ae549
Merge branch 'version-3' into cbor
mullermp Apr 30, 2024
85b65f4
Malformed request handling - broken protocol tests
mullermp Apr 30, 2024
3e8d7d2
New protocol tests
mullermp Apr 30, 2024
eca72ac
Update cbor decode tests from upstream
alextwoods May 20, 2024
01ad272
Add new float16 protocol tests
alextwoods May 20, 2024
3bd66e3
Merge branch 'version-3' into cbor
mullermp May 22, 2024
0b46348
Minimum core version bump
mullermp May 22, 2024
ec3615e
Change format of ignore list to not be per-engine keys
mullermp May 22, 2024
570b4e0
PR feedback [ci skip]
mullermp May 22, 2024
22a5d2a
Merge branch 'version-3' into cbor
mullermp May 22, 2024
37def58
Event stream support and refactor protocols
mullermp May 22, 2024
85c5cd2
Fix tests
mullermp May 22, 2024
25f6e54
Handle event stream responses correctly
mullermp May 27, 2024
d2a2968
force encoding of blobs to binary
alextwoods May 22, 2024
396d50d
Merge branch 'cbor' of github.com:aws/aws-sdk-ruby into cbor
alextwoods May 30, 2024
db5fbba
Bubble up force encoding binary
mullermp May 31, 2024
0ab6400
Revert "Bubble up force encoding binary"
mullermp May 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ on:
jobs:
changelog_comment_pr:
runs-on: ubuntu-latest
name: Comment when Changelog is missing
name: Comment when CHANGELOG entry is missing
steps:
- id: file_changes
uses: trilom/file-changes-action@v1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}

- name: Comment PR
if: ${{!contains(steps.file_changes.outputs.files_modified, 'gems/aws-sdk-core/CHANGELOG.md')}}
- name: Comment on PR
if: ${{!contains(steps.changed-files.outputs.all_changed_files, 'gems/aws-sdk-core/CHANGELOG.md')}}
uses: thollander/actions-comment-pull-request@main
with:
message: 'You have made a change to core without a corresponding change to the CHANGELOG.md. This change will not result in a new version and will not published unless an entry is added to CHANGELOG.md'
message: 'You have made a change to core without a corresponding change to the CHANGELOG.md. This change will not result in a new version and will not published unless an entry is added to CHANGELOG.md.'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ gem 'aws-crt' if ENV['CRT']
gem 'http-2'
gem 'jmespath'

# json and xml parsers
# protocol parsers
mullermp marked this conversation as resolved.
Show resolved Hide resolved
gem 'json'
gem 'nokogiri', '>= 1.6.8.1'
gem 'oga'
gem 'rexml'

# These json and xml parsers do not have java gems
# These protocol parsers do not have java gems
unless defined?(JRUBY_VERSION)
gem 'libxml-ruby'
gem 'oj'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def initialize(options)
@method_name = options.fetch(:method_name)
@operation = options.fetch(:operation)
@api = options.fetch(:api)
@protocol = options.fetch(:protocol)
@client_examples = options.fetch(:client_examples, [])
@examples = options.fetch(:examples)
@module_name = options.fetch(:module_name)
Expand Down Expand Up @@ -279,7 +280,7 @@ def waiters_tag(waiters)

def see_also_tag(operation, api)
uid = api['metadata']['uid']
if api['metadata']['protocol'] != 'api-gateway' && Crosslink.taggable?(uid)
if @protocol != 'api-gateway' && Crosslink.taggable?(uid)
"# " + Crosslink.tag_string(uid, operation)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def initialize(options)
api = options.fetch(:api)
examples = options.fetch(:examples, {})
module_name = options.fetch(:module_name)
protocol = options.fetch(:protocol)
protocol_settings = options.fetch(:protocol_settings, {})
client_examples = options.fetch(:client_examples, {})
paginators = options.fetch(:paginators, {})
Expand Down Expand Up @@ -41,6 +42,7 @@ def initialize(options)
method_name: method_name,
operation: operation,
api: api,
protocol: protocol,
examples: examples,
client_examples: client_examples[method_name] || [],
async_client: true
Expand All @@ -60,6 +62,7 @@ def initialize(options)
method_name: method_name,
operation: operation,
api: api,
protocol: protocol,
examples: examples,
client_examples: client_examples[method_name] || [],
async_client: false
Expand All @@ -80,6 +83,7 @@ def initialize(options)
method_name: method_name,
operation: operation,
api: api,
protocol: protocol,
examples: examples,
client_examples: client_examples[method_name] || [],
async_client: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,13 @@ def client_class(codegenerated_plugins)
Views::ClientClass.new(
service_identifier: @service.identifier,
service_name: @service.name,
protocol: @service.protocol,
protocol_settings: @service.protocol_settings,
module_name: @service.module_name,
gem_name: @service.gem_name,
gem_version: @service.gem_version,
aws_sdk_core_lib_path: @aws_sdk_core_lib_path,
client_examples: @client_examples,
protocol: @service.protocol,
signature_version: @service.signature_version,
require_endpoint_discovery: @service.require_endpoint_discovery,
add_plugins: @service.add_plugins,
Expand All @@ -210,12 +210,12 @@ def async_client_class(codegenerated_plugins)
Views::AsyncClientClass.new(
service_identifier: @service.identifier,
service_name: @service.name,
protocol: @service.protocol,
protocol_settings: @service.protocol_settings,
module_name: @service.module_name,
gem_name: @service.gem_name,
gem_version: @service.gem_version,
aws_sdk_core_lib_path: @aws_sdk_core_lib_path,
protocol: @service.protocol,
signature_version: @service.signature_version,
add_plugins: @service.add_plugins,
remove_plugins: @service.remove_plugins,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def protocol_plugins(protocol)
'rest-xml' => { 'Aws::Plugins::Protocols::RestXml' => "#{core_plugins}/protocols/rest_xml.rb" },
'query' => { 'Aws::Plugins::Protocols::Query' => "#{core_plugins}/protocols/query.rb" },
'ec2' => { 'Aws::Plugins::Protocols::EC2' => "#{core_plugins}/protocols/ec2.rb" },
'smithy-rpc-v2-cbor' => { 'Aws::Plugins::Protocols::RpcV2' => "#{core_plugins}/protocols/rpc_v2.rb" },
'api-gateway' => {
'Aws::Plugins::Protocols::ApiGateway' => "#{core_plugins}/protocols/api_gateway.rb",
'Aws::Plugins::ApiKey' => "#{core_plugins}/api_key.rb",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,25 @@

module AwsSdkCodeGenerator
class Service
# Ordered priority list of supported protocols
# api-gateway is a special case and is always first.
SUPPORTED_PROTOCOLS = %w[
api-gateway
smithy-rpc-v2-cbor
json_1.0
json_1.1
rest-json
rest-xml
query ec2
]

# @param [Hash] options
# @option options [required, String] :gem_version Gem version, e.g. "1.0.0".
# @option options [required, String] :name The service name, e.g. "S3"
# @option options [String] :module_name The service module name, defaults
# to "Aws::#{name}", e.g. "Aws::S3".
# @option options [String] :gem_name The gem name, defaults to
# "aws-sdk-#{name}", e.g. "aws-sdk-s3".
# @option options [required, String] :gem_version Gem version, e.g. "1.0.0".
# @option options [required, Hash, String] :api
# @option options [Hash, String] :docs
# @option options [Hash, String] :paginators
Expand All @@ -21,44 +34,48 @@ class Service
# @option options [Hash] :add_plugins ({})
# @option options [Hash] :remove_plugins ([])
# @option options [Boolean] :deprecated (false)
# @option options [String] :default_endpoint (nil)
# @option options [String] :endpoints_key (nil)
def initialize(options)
@name = options.fetch(:name)
@identifier = name.downcase
@module_name = options[:module_name] || "Aws::#{name}"
@gem_name = options[:gem_name] || "aws-sdk-#{identifier}"
@gem_version = options.fetch(:gem_version)

@api = load_json(options.fetch(:api))
unless @api['metadata']['protocol'] == 'api-gateway'
# Dont reply on API Gateway doc.json

# computed attributes
metadata = @api.fetch('metadata')
@protocol = select_protocol(metadata)
@protocol_settings = metadata['protocolSettings'] || {}
@api_version = metadata['apiVersion']
@signature_version = metadata['signatureVersion']
@full_name = metadata['serviceFullName']
@short_name = metadata['serviceAbbreviation'] || @full_name

# Dont reply on API Gateway doc.json
unless @protocol == 'api-gateway'
ApplyDocs.new(@api).apply(load_json(options[:docs]))
end
@paginators = load_json(options[:paginators])
@waiters = load_json(options[:waiters])
@resources = load_json(options[:resources])
@examples = load_json(options[:examples])
@smoke_tests = load_json(options[:smoke_tests])
unless options[:legacy_endpoints]
@endpoint_rules = load_json(options[:endpoint_rules])
@endpoint_tests = load_json(options[:endpoint_tests])
end
@smoke_tests = load_json(options[:smoke_tests])

@gem_dependencies = options[:gem_dependencies] || {}
@add_plugins = options[:add_plugins] || {}
@remove_plugins = options[:remove_plugins] || []
@deprecated = options[:deprecated] || false
@default_endpoint = options[:default_endpoint] # APIG custom service only
@endpoints_key = options.fetch(:endpoints_key, nil)
# APIG custom service only
@default_endpoint = options[:default_endpoint]

# computed attributes
@protocol = api.fetch('metadata').fetch('protocol')
@protocol_settings = api.fetch('metadata')['protocolSettings'] || {}
@api_version = api.fetch('metadata')['apiVersion']
@signature_version = api.fetch('metadata')['signatureVersion']
@full_name = api.fetch('metadata')['serviceFullName']
@short_name = api.fetch('metadata')['serviceAbbreviation'] || @full_name
@require_endpoint_discovery = api.fetch('operations', []).any? do |_, o|
o['endpointdiscovery'] && o['endpointdiscovery']['required']
end
@deprecated = options[:deprecated] || false
@require_endpoint_discovery = endpoint_discovery_required?
end

# @return [String] The service name, e.g. "S3"
Expand Down Expand Up @@ -129,6 +146,9 @@ def included_in_core?
# @return [String] The service protocol, e.g. "json", "query", etc.
attr_reader :protocol

# @return [Array<String>] The list of supported protocols
attr_reader :protocols

# @return [Hash] The service protocol settings
attr_reader :protocol_settings

Expand Down Expand Up @@ -174,6 +194,29 @@ def inspect

private

def select_protocol(metadata)
protocols = metadata.fetch('protocols', [metadata['protocol']])
protocol = SUPPORTED_PROTOCOLS.find do |supported_protocol|
if %w[json_1.0 json_1.1].include?(supported_protocol)
supported_protocol, version = supported_protocol.split('_')
end

if protocols.include?(supported_protocol) &&
(version.nil? || version == metadata['jsonVersion'])
return supported_protocol
end
end
return protocol if protocol

raise "unsupported protocols `#{protocols.join(', ')}'"
end

def endpoint_discovery_required?
@api.fetch('operations', []).any? do |_, o|
o['endpointdiscovery'] && o['endpointdiscovery']['required']
end
end

def load_json(value)
case value
when nil then nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,26 @@ class ClientApiModule < View
SHAPE_KEYS = {
# keep
'flattened' => true,
'timestampFormat' => true, # glacier api customization
'timestampFormat' => true,
'xmlNamespace' => true,
'streaming' => true, # transfer-encoding
'requiresLength' => true, # transfer-encoding
'union' => false, # should remain false
'streaming' => true,
'requiresLength' => true,
'union' => false, # not ignored - should remain false
mullermp marked this conversation as resolved.
Show resolved Hide resolved
'document' => true,
'jsonvalue' => true,
'error' => true, # parsing customized error code in query protocol
'locationName' => true, # to recognize xmlName defined on shape
'error' => true,
'locationName' => true,
# ignore
# event stream modeling
'event' => false,
'eventstream' => false,
'eventheader' => false,
'eventpayload' => false,
# ignore
'exceptionEvent' => false, # internal, exceptions cannot be events
# other
'synthetic' => false,
'box' => false,
'fault' => false,
'exception_event' => false, # internal, exceptions cannot be events
'deprecated' => false,
'deprecatedMessage' => false,
'type' => false,
Expand All @@ -68,7 +69,7 @@ class ClientApiModule < View
}

METADATA_KEYS = {
# keep all
# keep
'endpointPrefix' => true,
'signatureVersion' => true,
'signingName' => true,
Expand All @@ -78,18 +79,18 @@ class ClientApiModule < View
'targetPrefix' => true,
'jsonVersion' => true,
'errorPrefix' => true,
'timestampFormat' => true, # glacier api customization
'timestampFormat' => true,
'xmlNamespace' => true,
'protocolSettings' => {}, # current unused unless for h2 exclude
'protocolSettings' => {},
'serviceId' => true,
'apiVersion' => true,
'checksumFormat' => true,
'globalEndpoint' => true,
'serviceAbbreviation' => true,
'uid' => true,
'awsQueryCompatible' => true, # AwsQuery migration
'awsQueryCompatible' => true,
# ignore
'ripServiceName' => true
'ripServiceName' => false
}

# @option options [required, Service] :service
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def structures
# exceptions will not have the event trait.
shape['members'].each do |name, ref|
if !!@service.api['shapes'][ref['shape']]['exception']
@service.api['shapes'][ref['shape']]['exception_event'] = true
@service.api['shapes'][ref['shape']]['exceptionEvent'] = true
end
end
end
Expand Down Expand Up @@ -90,7 +90,7 @@ def struct_members(shape)
returns: AwsSdkCodeGenerator::RBS.to_type(member_ref, @api)
)
end
if shape['event'] || shape['exception_event']
if shape['event'] || shape['exceptionEvent']
members << StructMember.new(
member_name: 'event_type',
returns: 'untyped'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def structures
# exceptions will not have the event trait.
shape['members'].each do |name, ref|
if !!@service.api['shapes'][ref['shape']]['exception']
@service.api['shapes'][ref['shape']]['exception_event'] = true
@service.api['shapes'][ref['shape']]['exceptionEvent'] = true
end
end
end
Expand Down Expand Up @@ -92,7 +92,7 @@ def struct_members(shape)
sensitive: sensitive
)
end
if shape['event'] || shape['exception_event']
if shape['event'] || shape['exceptionEvent']
members << StructMember.new(member_name: 'event_type')
end
members
Expand Down Expand Up @@ -180,7 +180,7 @@ def attribute_macros_docs(shape_name)

def see_also_tag(shape_name)
uid = @api['metadata']['uid']
if @api['metadata']['protocol'] != 'api-gateway' && Crosslink.taggable?(uid)
if @service.protocol != 'api-gateway' && Crosslink.taggable?(uid)
Crosslink.tag_string(uid, shape_name)
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"metadata": {
"endpointPrefix": "svcname",
"endpointPrefix": "svc",
"serviceId": "sample_svc",
"protocol": "rest-json"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"metadata": {
"endpointPrefix": "svcname",
"endpointPrefix": "svc",
"serviceId": "sample_svc",
"protocol": "rest-json"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"metadata": {
"endpointPrefix": "svcname",
"endpointPrefix": "svc",
"serviceId": "sample_svc",
"protocol": "rest-json"
},
Expand Down