build_tools/customizations.rb (214 lines of code) (raw):

# frozen_string_literal: true module BuildTools module Customizations @api_customizations = {} @doc_customizations = {} @example_customizations = {} @smoke_customizations = {} class << self def api(svc_name, &block) @api_customizations[svc_name] = block end def doc(svc_name, &block) @doc_customizations[svc_name] = block end def example(svc_name, &block) @example_customizations[svc_name] = block end def smoke(svc_name, &block) @smoke_customizations[svc_name] = block end def apply_api_customizations(svc_name, api) @api_customizations[svc_name].call(api) if @api_customizations[svc_name] end def apply_doc_customizations(svc_name, docs) @doc_customizations[svc_name].call(docs) if @doc_customizations[svc_name] end def apply_example_customizations(svc_name, examples) @example_customizations[svc_name].call(examples) if @example_customizations[svc_name] end def apply_smoke_customizations(svc_name, smoke) @smoke_customizations[svc_name].call(smoke) if @smoke_customizations[svc_name] end private def dynamodb_example_deep_transform(subsegment, keys) if subsegment.is_a?(Hash) if subsegment.keys.size == 1 && keys.include?(subsegment.keys.first) subsegment[subsegment.keys.first] # reduce to value only else subsegment.each do |key, value| subsegment[key] = dynamodb_example_deep_transform(value, keys) end end elsif subsegment.is_a?(Array) subsegment.map do |item| dynamodb_example_deep_transform(item, keys) end else subsegment end end end api('CloudFront') do |api| api['shapes'].each do |_, shape| if shape['members'] && shape['members']['MaxItems'] && shape['members']['MaxItems']['shape'] == 'string' shape['members']['MaxItems']['shape'] = 'integer' end end api['operations'].keys.each do |name| symbolized = name.sub(/\d{4}_\d{2}_\d{2}$/, '') api['operations'][symbolized] = api['operations'].delete(name) end end api('EC2') do |api| if ENV['DOCSTRINGS'] members = api['shapes']['CopySnapshotRequest']['members'] members.delete('DestinationRegion') members.delete('PresignedUrl') end end api('Glacier') do |api| api['shapes']['Timestamp'] = { 'type' => 'timestamp', 'timestampFormat' => 'iso8601', } api['shapes'].each do |_, shape| if shape['members'] shape['members'].each do |name, ref| case name when /date/i then ref['shape'] = 'Timestamp' when 'limit' then ref['shape'] = 'Size' when 'partSize' then ref['shape'] = 'Size' when 'archiveSize' then ref['shape'] = 'Size' end end end end end api('ImportExport') do |api| api['metadata']['serviceId'] ||= 'importexport' api['operations'].each do |_, operation| operation['http']['requestUri'] = '/' end end api('Lambda') do |api| api['shapes']['Timestamp']['type'] = 'timestamp' end # Cross Region Copying %w[RDS Neptune DocDB].each do |service| operations = %w[ CopyDBClusterSnapshotMessage CreateDBClusterMessage ] if service == 'RDS' operations += %w[ CopyDBSnapshotMessage CreateDBInstanceReadReplicaMessage StartDBInstanceAutomatedBackupsReplicationMessage ] end api(service) do |api| operations.each do |shape_name| api['shapes'][shape_name]['members']['SourceRegion'] = { 'shape' => 'String' } end end doc(service) do |docs| operations.each do |shape_name| docs['shapes']['String']['refs']["#{shape_name}$SourceRegion"] = '<p>The source region of the snapshot. This is only needed when '\ 'the shapshot is encrypted and in a different region.</p>' end end end api('Route53') do |api| api['shapes']['PageMaxItems']['type'] = 'integer' end api('S3') do |api| api['metadata'].delete('signatureVersion') # handled by endpoints 2.0 api['operations'].each do |_key, operation| # requestUri should always exist. Remove bucket from path # and preserve request uri as / if operation['http'] && operation['http']['requestUri'] operation['http']['requestUri'].gsub!('/{Bucket}', '/') operation['http']['requestUri'].gsub!('//', '/') end end # Ensure Expires is a timestamp regardless of model to be backwards # compatible. Add ExpiresString in cases where Expires cannot be parsed # as a Timestamp. api['shapes']['Expires'] = { 'type' => 'timestamp' } api['shapes']['ExpiresString'] = { 'type' => 'string' } %w(HeadObjectOutput GetObjectOutput).each do |shape| members = api['shapes'][shape]['members'] # inject ExpiresString directly after Expires api['shapes'][shape]['members'] = members.inject({}) do |h, (k,v)| h[k] = v if k == 'Expires' h['ExpiresString'] = { 'shape' => 'ExpiresString', 'location' => 'header', 'locationName' => 'Expires', } end h end end end api('S3Control') do |api| # handled by endpoints 2.0 api['operations'].each do |_key, operation| # Removes the accountId host prefix trait and requiredness. # Checks the hostPrefix labels and removes only those from the API. next unless operation['endpoint'] && (host_prefix = operation['endpoint']['hostPrefix']) && host_prefix == '{AccountId}.' operation['endpoint'].delete('hostPrefix') host_prefix.gsub(/\{.+?\}/) do |label| label = label.delete('{}') input_shape = api['shapes'][operation['input']['shape']] input_shape['members'][label].delete('hostLabel') input_shape['required']&.delete(label) end end end # SimpleDB does not adhere to the query protocol guidelines because it # uses both flattened and locationName. Query protocol is supposed to # ignore location name (xmlName) when flattened (xmlFlattened) is used. api('SimpleDB') do |api| api['metadata']['serviceId'] ||= 'SimpleDB' api['shapes'].each do |_, shape| next unless shape['type'] == 'structure' shape['members'].each do |_, member| member_ref = api['shapes'][member['shape']] next unless member_ref['flattened'] member['locationName'] = member_ref['member']['locationName'] end end end api('SQS') do |api| api['metadata']['errorPrefix'] = 'AWS.SimpleQueueService.' api['shapes']['StringList']['flattened'] = true api['shapes']['BinaryList']['flattened'] = true api['shapes']['MessageAttributeValue']['members']['StringListValues'].delete('flattened') api['shapes']['MessageAttributeValue']['members']['BinaryListValues'].delete('flattened') end api('STS') do |api| operations = %w(AssumeRoleWithSAML AssumeRoleWithWebIdentity) operations.each do |operation| api['operations'][operation]['auth'] = ['smithy.api#noAuth'] end end smoke('DSQL') do |smoke| test = smoke['testCases'].find do |test_case| test_case['id'] == 'GetClusterNotFound' end test['input']['identifier'] = 'a' * 26 end smoke('ElasticTranscoder') do |smoke| # discontinued service smoke['testCases'] = [] end smoke('NetworkFlowMonitor') do |smoke| test = smoke['testCases'].find do |test_case| test_case['id'] == 'GetMonitorSuccess' end test['expectation'] = { 'failure' => {} } end smoke('ObservabilityAdmin') do |smoke| test = smoke['testCases'].find do |test_case| test_case['id'] == 'GetTelemetryEvaluationStatusForOrganization' end test['expectation'] = { 'failure' => { 'errorId' => 'ValidationException' } } test = smoke['testCases'].find do |test_case| test_case['id'] == 'GetTelemetryEvaluationStatus' end test['expectation'] = { 'success' => {} } end end end