Skip to content

Commit a60eb4b

Browse files
committed
Pull request #1456: CATS-1057: Verify that S3 bucket exists on startup, create it if not
Merge in CATS/clowder from CATS-1057-verify-that-s3-bucket-exists-on-startup to develop * commit 'aed0c9995b0e4032db335f21f5d62006271a5b9f': Add back Logger warning message on bucket create Verify bucket exists on startup, create it if not
2 parents 14d866c + aed0c99 commit a60eb4b

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ of these changes a reindex of Elasticsearch is required. This can be started by
2323
- Ability to filter the files and folders in a dataset when sorting is enabled.
2424
- Visualize existing relations between datasets on the dataset page. This can be extended other resource types.
2525
[CATS-1000](https://opensource.ncsa.illinois.edu/jira/browse/CATS-1000)
26+
- S3ByteStorageService should verify bucket existence on startup and create if it does not exist.
27+
[CATS-1057](https://opensource.ncsa.illinois.edu/jira/browse/CATS-1057)
2628

2729
### Fixed
2830
- When adding tags to a section of an image, show the new tag without having to refresh the page.

app/services/s3/S3ByteStorageService.scala

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import models.UUID
66
import com.amazonaws.auth.{AWSStaticCredentialsProvider, BasicAWSCredentials}
77
import com.amazonaws.client.builder.AwsClientBuilder
88
import com.amazonaws.regions.Regions
9-
import com.amazonaws.services.s3.model.{GetObjectRequest, ObjectMetadata}
9+
import com.amazonaws.services.s3.model.{HeadBucketRequest, CreateBucketRequest, GetObjectRequest, ObjectMetadata}
1010
import com.amazonaws.services.s3.{AmazonS3, AmazonS3ClientBuilder}
1111
import com.amazonaws.{AmazonClientException, ClientConfiguration}
1212
import com.google.inject.Inject
@@ -46,6 +46,42 @@ object S3ByteStorageService {
4646
*/
4747
class S3ByteStorageService @Inject()() extends ByteStorageService {
4848

49+
50+
// Only run a single thread at a time when verifying bucket existence
51+
synchronized {
52+
Play.current.configuration.getString(S3ByteStorageService.BucketName) match {
53+
case Some(bucketName) => {
54+
try {
55+
// Validate configuration by checking for bucket existence on startup
56+
this.s3Bucket.headBucket(new HeadBucketRequest(bucketName))
57+
} catch {
58+
case sdke @ (_: AmazonClientException | _: AmazonServiceException) => {
59+
if (sdke.getMessage.contains("Status Code: 404")) {
60+
Logger.warn("Configured S3 bucket does not exist, attempting to create it now...")
61+
try {
62+
// Bucket does not exist - create the bucket
63+
this.s3Bucket.createBucket(new CreateBucketRequest(bucketName))
64+
} catch {
65+
// Bucket could not be created - abort
66+
case _: Throwable => throw new RuntimeException("Bad S3 configuration: Bucket does not exist and could not be created.")
67+
}
68+
} else if (sdke.getMessage.contains("Status Code: 403")) {
69+
// Bucket exists, but you do not have permission to access it
70+
throw new RuntimeException("Bad S3 configuration: You do not have access to the configured bucket.")
71+
} else {
72+
// Unknown error - print status code for further investigation
73+
val errMsg = sdke.getLocalizedMessage
74+
Logger.error(errMsg)
75+
throw new RuntimeException("Bad S3 configuration: an unknown error has occurred - " + errMsg)
76+
}
77+
}
78+
case _: Throwable => handleUnknownError(_)
79+
}
80+
}
81+
case _ => throw new RuntimeException("Bad S3 configuration: verify that you have set all configuration options.")
82+
}
83+
}
84+
4985
/**
5086
* Grabs config parameters from Clowder to return a
5187
* AmazonS3 pointing at the configured service endpoint.

0 commit comments

Comments
 (0)