Skip to content

Commit

Permalink
Merge pull request #102 from swift-aws/glacier_fixes
Browse files Browse the repository at this point in the history
fixes for Glacier Service
  • Loading branch information
jonnymacs authored Mar 4, 2019
2 parents 23ecff2 + 1f3f77a commit a1ff6c0
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 102 deletions.
12 changes: 6 additions & 6 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/swift-aws/aws-sdk-swift-core.git",
"state": {
"branch": null,
"revision": "ee093b1f7b9114bc12bd629c43e64c216c7efd89",
"version": "2.0.0-rc.4"
"revision": "aba1a0b4da354e8dbded0677b0b82571b4b8c32b",
"version": "2.0.0-rc.6"
}
},
{
Expand All @@ -33,17 +33,17 @@
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
"revision": "a20e129c22ad00a51c902dca54a5456f90664780",
"version": "1.12.0"
"revision": "87dbd0216c47ea2e7ddb1b545271b716e03b943e",
"version": "1.13.1"
}
},
{
"package": "swift-nio-ssl",
"repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
"state": {
"branch": null,
"revision": "db16c3a90b101bb53b26a58867a344ad428072e0",
"version": "1.3.2"
"revision": "0f3999f3e3c359cc74480c292644c3419e44a12f",
"version": "1.4.0"
}
},
{
Expand Down
7 changes: 4 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ let package = Package(
name: "AWSSDKSwift",
products: [
.executable(name: "aws-sdk-swift-codegen", targets: ["CodeGenerator"]),
.library(name: "AWSSDKSwift", targets: ["ACM","ACMPCA","APIGateway","AlexaForBusiness","Amplify","AppMesh","AppStream","AppSync","ApplicationAutoScaling","ApplicationDiscoveryService","Athena","AutoScaling","AutoScalingPlans","Batch","Budgets","Chime","Cloud9","CloudDirectory","CloudFormation","CloudFront","CloudHSM","CloudHSMV2","CloudSearch","CloudSearchDomain","CloudTrail","CloudWatch","CloudWatchEvents","CloudWatchLogs","CodeBuild","CodeCommit","CodeDeploy","CodePipeline","CodeStar","CognitoIdentity","CognitoIdentityProvider","CognitoSync","Comprehend","ComprehendMedical","ConfigService","Connect","CostExplorer","CostandUsageReportService","DAX","DLM","DataPipeline","DataSync","DatabaseMigrationService","DeviceFarm","DirectConnect","DirectoryService","DynamoDB","DynamoDBStreams","EC2","ECR","ECS","EFS","EKS","ELB","ELBV2","EMR","ElastiCache","ElasticBeanstalk","ElasticTranscoder","ElasticsearchService","FMS","FSx","Firehose","GameLift","Glacier","GlobalAccelerator","Glue","Greengrass","GuardDuty","Health","IAM","ImportExport","Inspector","IoT","IoT1ClickDevicesService","IoT1ClickProjects","IoTAnalytics","IoTDataPlane","IoTJobsDataPlane","KMS","Kafka","Kinesis","KinesisAnalytics","KinesisAnalyticsV2","KinesisVideo","KinesisVideoArchivedMedia","KinesisVideoMedia","Lambda","LexModelBuildingService","LexRuntimeService","LicenseManager","Lightsail","MQ","MTurk","MachineLearning","Macie","MarketplaceCommerceAnalytics","MarketplaceEntitlementService","MarketplaceMetering","MediaConnect","MediaConvert","MediaLive","MediaPackage","MediaStore","MediaStoreData","MediaTailor","MigrationHub","Mobile","MobileAnalytics","Neptune","OpsWorks","OpsWorksCM","Organizations","PI","Pinpoint","PinpointEmail","PinpointSMSVoice","Polly","Pricing","QuickSight","RAM","RDS","RDSDataService","Redshift","Rekognition","ResourceGroups","ResourceGroupsTaggingAPI","RoboMaker","Route53","Route53Domains","Route53Resolver","S3","S3Control","S3Middleware","SES","SFN","SMS","SNS","SQS","SSM","STS","SWF","SageMaker","SageMakerRuntime","SecretsManager","SecurityHub","ServerlessApplicationRepository","ServiceCatalog","ServiceDiscovery","Shield","Signer","SimpleDB","Snowball","StorageGateway","Support","TranscribeService","Transfer","Translate","WAF","WAFRegional","WorkDocs","WorkMail","WorkSpaces","XRay"]),
.library(name: "AWSSDKSwift", targets: ["ACM","ACMPCA","APIGateway","AlexaForBusiness","Amplify","AppMesh","AppStream","AppSync","ApplicationAutoScaling","ApplicationDiscoveryService","Athena","AutoScaling","AutoScalingPlans","Batch","Budgets","Chime","Cloud9","CloudDirectory","CloudFormation","CloudFront","CloudHSM","CloudHSMV2","CloudSearch","CloudSearchDomain","CloudTrail","CloudWatch","CloudWatchEvents","CloudWatchLogs","CodeBuild","CodeCommit","CodeDeploy","CodePipeline","CodeStar","CognitoIdentity","CognitoIdentityProvider","CognitoSync","Comprehend","ComprehendMedical","ConfigService","Connect","CostExplorer","CostandUsageReportService","DAX","DLM","DataPipeline","DataSync","DatabaseMigrationService","DeviceFarm","DirectConnect","DirectoryService","DynamoDB","DynamoDBStreams","EC2","ECR","ECS","EFS","EKS","ELB","ELBV2","EMR","ElastiCache","ElasticBeanstalk","ElasticTranscoder","ElasticsearchService","FMS","FSx","Firehose","GameLift","Glacier","GlacierMiddleware","GlobalAccelerator","Glue","Greengrass","GuardDuty","Health","IAM","ImportExport","Inspector","IoT","IoT1ClickDevicesService","IoT1ClickProjects","IoTAnalytics","IoTDataPlane","IoTJobsDataPlane","KMS","Kafka","Kinesis","KinesisAnalytics","KinesisAnalyticsV2","KinesisVideo","KinesisVideoArchivedMedia","KinesisVideoMedia","Lambda","LexModelBuildingService","LexRuntimeService","LicenseManager","Lightsail","MQ","MTurk","MachineLearning","Macie","MarketplaceCommerceAnalytics","MarketplaceEntitlementService","MarketplaceMetering","MediaConnect","MediaConvert","MediaLive","MediaPackage","MediaStore","MediaStoreData","MediaTailor","MigrationHub","Mobile","MobileAnalytics","Neptune","OpsWorks","OpsWorksCM","Organizations","PI","Pinpoint","PinpointEmail","PinpointSMSVoice","Polly","Pricing","QuickSight","RAM","RDS","RDSDataService","Redshift","Rekognition","ResourceGroups","ResourceGroupsTaggingAPI","RoboMaker","Route53","Route53Domains","Route53Resolver","S3","S3Control","S3Middleware","SES","SFN","SMS","SNS","SQS","SSM","STS","SWF","SageMaker","SageMakerRuntime","SecretsManager","SecurityHub","ServerlessApplicationRepository","ServiceCatalog","ServiceDiscovery","Shield","Signer","SimpleDB","Snowball","StorageGateway","Support","TranscribeService","Transfer","Translate","WAF","WAFRegional","WorkDocs","WorkMail","WorkSpaces","XRay"]),

.library(name: "ACM", targets: ["ACM"]),
.library(name: "ACMPCA", targets: ["ACMPCA"]),
Expand Down Expand Up @@ -176,7 +176,7 @@ let package = Package(
.library(name: "XRay", targets: ["XRay"])
],
dependencies: [
.package(url: "https://github.com/swift-aws/aws-sdk-swift-core.git", .upToNextMajor(from: "2.0.0-rc.4")),
.package(url: "https://github.com/swift-aws/aws-sdk-swift-core.git", .upToNextMajor(from: "2.0.0-rc.6")),
.package(url: "https://github.com/IBM-Swift/SwiftyJSON.git", .upToNextMajor(from: "17.0.2"))
],
targets: [
Expand Down Expand Up @@ -250,7 +250,7 @@ let package = Package(
.target(name: "FSx", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/FSx"),
.target(name: "Firehose", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/Firehose"),
.target(name: "GameLift", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/GameLift"),
.target(name: "Glacier", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/Glacier"),
.target(name: "Glacier", dependencies: ["AWSSDKSwiftCore", "GlacierMiddleware"], path: "./Sources/AWSSDKSwift/Services/Glacier"),
.target(name: "GlobalAccelerator", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/GlobalAccelerator"),
.target(name: "Glue", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/Glue"),
.target(name: "Greengrass", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/Greengrass"),
Expand Down Expand Up @@ -349,6 +349,7 @@ let package = Package(
.target(name: "WorkMail", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/WorkMail"),
.target(name: "WorkSpaces", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/WorkSpaces"),
.target(name: "XRay", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Services/XRay"),
.target(name: "GlacierMiddleware", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Middlewares/Glacier"),
.target(name: "S3Middleware", dependencies: ["AWSSDKSwiftCore"], path: "./Sources/AWSSDKSwift/Middlewares/S3"),

.testTarget(name: "AWSSDKSwiftTests", dependencies: ["DynamoDB", "S3"])
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import Foundation
import AWSSDKSwiftCore

let MEGA_BYTE = 1024 * 1024

public struct GlacierRequestMiddleware: AWSRequestMiddleware {

let apiVersion: String

public init (apiVersion: String) {
self.apiVersion = apiVersion
}

public func chain(request: AWSRequest) throws -> AWSRequest {
var request = request
request.addValue(apiVersion, forHTTPHeaderField: "x-amz-glacier-version")

let treeHashHeader = "x-amz-sha256-tree-hash"

if request.httpHeaders[treeHashHeader] == nil {
if let data = try request.body.asData() {
let treeHash = computeTreeHash(data).hexdigest()
request.addValue(treeHash, forHTTPHeaderField: treeHashHeader)
}
}

return request
}

// ComputeTreeHash builds a tree hash root node given a Data Object
// Glacier tree hash to be derived from SHA256 hashes of 1MB
// chucks of the data.
//
// See http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html for more information.
//
fileprivate func computeTreeHash(_ data: Data) -> [UInt8] {
var shas: [[UInt8]] = []

if data.count < MEGA_BYTE {
shas.append(sha256(data))
} else {
var numParts = data.count / MEGA_BYTE
if data.count % MEGA_BYTE > 0 {
numParts += 1
}

var start: Int
var end: Int

for partNum in 0..<numParts {
start = partNum * MEGA_BYTE
if partNum == numParts - 1 {
end = data.count - 1
} else {
end = start + MEGA_BYTE - 1
}
shas.append(sha256(data.subdata(in: Range(start...end))))
}
}

while shas.count > 1 {
var tmpShas: [[UInt8]] = []
shas.forEachSlice(2, {
let pair = $0
guard var bytes1 = pair.first else { return }

if pair.count > 1, var bytes2 = pair.last {
tmpShas.append(sha256(&bytes1, &bytes2))
} else {
tmpShas.append(bytes1)
}
})
shas = tmpShas
}

return shas[0]
}

}

extension Array {
/*
[1,2,3,4,5].forEachSlice(2, { print($0) })
=> [1, 2]
=> [3, 4]
=> [5]
*/
public func forEachSlice(_ n: Int, _ body: (ArraySlice<Element>) throws -> Void) rethrows {
assert(n > 0, "n require to be greater than 0")

for from in stride(from: self.startIndex, to: self.endIndex, by: n) {
let to = Swift.min(from + n, self.endIndex)
try body(self[from..<to])
}
}
}
Loading

0 comments on commit a1ff6c0

Please sign in to comment.