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