Skip to content

Commit 9b73b89

Browse files
JamieB-gurtyley
andcommitted
Migrate to v2 of the AWS Java SDK for S3
The first part of the S3 migration. Panda settings require an instance of an `S3BucketLoader`. Panda comes with a default implementation for v1, but not v2, so this change creates one. This first requires a synchronous S3 client, which has been added to the `AWSv2` object alongside the existing asynchronous S3 client. Creating it here, rather than in the controller as before, allows it to be used more widely. Then the `getObject` method can be applied, with a `ResponseTransformer` to retrieve the "content" of the response, i.e. the object itself. We're removing `S3Client` as it became unused with #27391 Co-authored-by: Roberto Tyley <[email protected]>
1 parent 3a41c2e commit 9b73b89

File tree

10 files changed

+27
-146
lines changed

10 files changed

+27
-146
lines changed

admin/app/controllers/AdminControllers.scala

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package controllers
22
import com.amazonaws.regions.Regions
3-
import com.amazonaws.services.s3.AmazonS3ClientBuilder
3+
import software.amazon.awssdk.services.s3.S3Client
44
import com.softwaremill.macwire._
55
import common.PekkoAsync
66
import controllers.admin._
@@ -15,6 +15,7 @@ import play.api.mvc.ControllerComponents
1515
import services.{OphanApi, ParameterStoreService, RedirectService}
1616
import conf.Configuration.aws.mandatoryCredentials
1717
import org.apache.pekko.stream.Materializer
18+
import utils.AWSv2
1819

1920
trait AdminControllers {
2021
def pekkoAsync: PekkoAsync
@@ -44,20 +45,12 @@ trait AdminControllers {
4445
def dfpApi: DfpApi
4546
def parameterStoreService: ParameterStoreService
4647

47-
private lazy val s3Client = AmazonS3ClientBuilder
48-
.standard()
49-
.withRegion(Regions.EU_WEST_1)
50-
.withCredentials(
51-
mandatoryCredentials,
52-
)
53-
.build()
54-
5548
lazy val auth = new GuardianAuthWithExemptions(
5649
controllerComponents,
5750
wsClient,
5851
toolsDomainPrefix = "frontend",
5952
oauthCallbackPath = routes.GuardianAuthWithExemptions.oauthCallback.path,
60-
s3Client,
53+
AWSv2.S3Sync,
6154
system = "frontend-admin",
6255
extraDoNotAuthenticatePathPrefixes = Seq(
6356
// Date: 06 July 2021

article/app/AppLoader.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import _root_.commercial.targeting.TargetingLifecycle
2-
import org.apache.pekko.actor.{ActorSystem => PekkoActorSystem}
32
import app.{FrontendApplicationLoader, FrontendBuildInfo, FrontendComponents}
43
import com.softwaremill.macwire._
54
import common._
65
import common.dfp.DfpAgentLifecycle
7-
import concurrent.BlockingOperations
8-
import conf.{CachedHealthCheckLifeCycle, Configuration}
6+
import conf.CachedHealthCheckLifeCycle
97
import conf.switches.SwitchboardLifecycle
108
import contentapi.{CapiHttpClient, ContentApiClient, HttpClient}
119
import controllers.{ArticleControllers, HealthCheck}
1210
import dev.{DevAssetsController, DevParametersHttpRequestHandler}
1311
import http.{CommonFilters, CorsHttpErrorHandler}
1412
import jobs.StoreNavigationLifecycleComponent
1513
import model.ApplicationIdentity
14+
import org.apache.pekko.actor.{ActorSystem => PekkoActorSystem}
1615
import play.api.ApplicationLoader.Context
1716
import play.api.BuiltInComponentsFromContext
1817
import play.api.http.{HttpErrorHandler, HttpRequestHandler}
1918
import play.api.mvc.EssentialFilter
2019
import play.api.routing.Router
2120
import router.Routes
22-
import services.fronts.FrontJsonFapiLive
2321
import services.newsletters.{NewsletterApi, NewsletterSignupAgent, NewsletterSignupLifecycle}
2422
import services.ophan.SurgingContentAgentLifecycle
25-
import services.{NewspaperBooksAndSectionsAutoRefresh, OphanApi, S3Client, S3ClientImpl, SkimLinksCacheLifeCycle}
23+
import services.{NewspaperBooksAndSectionsAutoRefresh, OphanApi, SkimLinksCacheLifeCycle}
2624

2725
class AppLoader extends FrontendApplicationLoader {
2826
override def buildComponents(context: Context): FrontendComponents =

article/app/controllers/ArticleControllers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import model.ApplicationContext
66
import play.api.libs.ws.WSClient
77
import play.api.mvc.ControllerComponents
88
import renderers.DotcomRenderingService
9-
import services.{NewsletterService, NewspaperBookSectionTagAgent, NewspaperBookTagAgent, S3Client}
109
import services.newsletters.NewsletterSignupAgent
10+
import services.{NewsletterService, NewspaperBookSectionTagAgent, NewspaperBookTagAgent}
1111

1212
trait ArticleControllers {
1313
def contentApiClient: ContentApiClient

article/app/services/S3Client.scala

Lines changed: 0 additions & 97 deletions
This file was deleted.

article/test/TestAppLoader.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import app.FrontendComponents
2-
import services.S3Client
3-
import org.mockito.Mockito._
4-
import org.scalatestplus.mockito.MockitoSugar
52
import play.api.ApplicationLoader.Context
63
import play.api.BuiltInComponentsFromContext
74
import renderers.DotcomRenderingService
8-
import test.WithTestContentApiClient
9-
import test.DCRFake
5+
import test.{DCRFake, WithTestContentApiClient}
106

117
trait TestComponents extends WithTestContentApiClient {
128
self: AppComponents =>

common/app/http/GuardianAuthWithExemptions.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package http
22

33
import com.amazonaws.regions.Regions
4-
import com.amazonaws.services.s3.AmazonS3
4+
import software.amazon.awssdk.core.sync.ResponseTransformer
5+
import software.amazon.awssdk.services.s3.S3Client
56
import com.gu.pandomainauth.action.AuthActions
67
import com.gu.pandomainauth.model.AuthenticatedUser
78
import com.gu.pandomainauth.{PanDomain, PanDomainAuthSettingsRefresher, S3BucketLoader}
@@ -22,7 +23,7 @@ class GuardianAuthWithExemptions(
2223
override val wsClient: WSClient,
2324
toolsDomainPrefix: String,
2425
oauthCallbackPath: String,
25-
s3Client: AmazonS3,
26+
s3Client: S3Client,
2627
system: String,
2728
extraDoNotAuthenticatePathPrefixes: Seq[String],
2829
requiredEditorialPermissionName: String,
@@ -57,7 +58,13 @@ class GuardianAuthWithExemptions(
5758
override lazy val panDomainSettings = PanDomainAuthSettingsRefresher(
5859
domain = toolsDomainSuffix,
5960
system,
60-
S3BucketLoader.forAwsSdkV1(s3Client, "pan-domain-auth-settings"),
61+
new S3BucketLoader {
62+
def inputStreamFetching(key: String) =
63+
s3Client.getObject(
64+
_.bucket("pan-domain-auth-settings").key(key),
65+
ResponseTransformer.toInputStream(),
66+
)
67+
},
6168
)
6269

6370
override def authCallbackUrl = s"https://$toolsDomainPrefix.$toolsDomainSuffix$oauthCallbackPath"

common/app/services/S3.scala

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ trait S3 extends GuLogging {
1919

2020
lazy val bucket = Configuration.aws.frontendStoreBucket
2121

22-
lazy val client: Option[AmazonS3] = Configuration.aws.credentials.map { credentials =>
22+
lazy private val client: Option[AmazonS3] = Configuration.aws.credentials.map { credentials =>
2323
AmazonS3Client.builder
2424
.withCredentials(credentials)
2525
.withRegion(conf.Configuration.aws.region)
@@ -76,11 +76,6 @@ trait S3 extends GuLogging {
7676
put(key: String, value: String, contentType: String, PublicRead)
7777
}
7878

79-
def putPublic(key: String, file: File, contentType: String): Unit = {
80-
val request = new PutObjectRequest(bucket, key, file).withCannedAcl(PublicRead)
81-
client.foreach(_.putObject(request))
82-
}
83-
8479
def putPrivate(key: String, value: String, contentType: String): Unit = {
8580
put(key: String, value: String, contentType: String, Private)
8681
}
@@ -169,7 +164,6 @@ object S3FrontsApi extends S3 {
169164
object S3Archive extends S3 {
170165
override lazy val bucket: String =
171166
if (Configuration.environment.isNonProd) "aws-frontend-archive-code" else "aws-frontend-archive"
172-
def getHtml(path: String): Option[String] = get(path)
173167
}
174168

175169
object S3ArchiveOriginals extends S3 {

common/app/utils/AWSv2.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder
55
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient
66
import software.amazon.awssdk.regions.Region
77
import software.amazon.awssdk.regions.Region.EU_WEST_1
8-
import software.amazon.awssdk.services.s3.{S3AsyncClient, S3AsyncClientBuilder}
8+
import software.amazon.awssdk.services.s3.{S3AsyncClient, S3AsyncClientBuilder, S3Client, S3ClientBuilder}
99
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider
1010
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest
1111
import software.amazon.awssdk.services.sts.{StsClient, StsClientBuilder}
@@ -29,6 +29,8 @@ object AWSv2 {
2929

3030
val S3Async: S3AsyncClient = buildS3AsyncClient(credentials)
3131

32+
val S3Sync: S3Client = build[S3Client, S3ClientBuilder](S3Client.builder())
33+
3234
val STS: StsClient = build[StsClient, StsClientBuilder](StsClient.builder())
3335

3436
def stsCredentials(devProfile: String, roleArn: String): AwsCredentialsProvider = credentialsForDevAndProd(

preview/app/AppLoader.scala

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import agents.MostViewedAgent
2-
import org.apache.pekko.actor.{ActorSystem => PekkoActorSystem}
32
import app.{FrontendApplicationLoader, FrontendComponents, LifecycleComponent}
4-
import com.amazonaws.regions.Regions
5-
import com.amazonaws.services.s3.AmazonS3ClientBuilder
63
import com.softwaremill.macwire._
74
import commercial.controllers.CommercialControllers
85
import commercial.targeting.TargetingLifecycle
@@ -17,15 +14,9 @@ import cricket.controllers.CricketControllers
1714
import dev.DevAssetsController
1815
import feed.OnwardJourneyLifecycle
1916
import football.controllers.FootballControllers
20-
import http.{
21-
Filters,
22-
GuardianAuthWithExemptions,
23-
PreviewContentSecurityPolicyFilter,
24-
PreviewNoCacheFilter,
25-
RequestIdFilter,
26-
routes,
27-
}
17+
import http.{routes, _}
2818
import model.ApplicationIdentity
19+
import org.apache.pekko.actor.{ActorSystem => PekkoActorSystem}
2920
import play.api.ApplicationLoader.Context
3021
import play.api.http.HttpErrorHandler
3122
import play.api.libs.ws.WSClient
@@ -38,7 +29,7 @@ import rugby.controllers.RugbyControllers
3829
import services.fronts.FrontJsonFapiDraft
3930
import services.newsletters.NewsletterSignupLifecycle
4031
import services.{ConfigAgentLifecycle, OphanApi, SkimLinksCacheLifeCycle}
41-
import conf.Configuration.aws.mandatoryCredentials
32+
import utils.AWSv2
4233

4334
trait PreviewLifecycleComponents
4435
extends SportServices
@@ -102,15 +93,12 @@ trait AppComponents
10293
with OnwardServices
10394
with ApplicationsServices {
10495

105-
private lazy val s3Client =
106-
AmazonS3ClientBuilder.standard().withRegion(Regions.EU_WEST_1).withCredentials(mandatoryCredentials).build()
107-
10896
private lazy val auth = new GuardianAuthWithExemptions(
10997
controllerComponents,
11098
wsClient,
11199
toolsDomainPrefix = "preview",
112100
oauthCallbackPath = routes.GuardianAuthWithExemptions.oauthCallback.path,
113-
s3Client,
101+
AWSv2.S3Sync,
114102
system = "preview",
115103
extraDoNotAuthenticatePathPrefixes = healthCheck.healthChecks.map(_.path),
116104
requiredEditorialPermissionName = "preview_access",

project/Dependencies.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object Dependencies {
1818
val awsDynamodb = "software.amazon.awssdk" % "dynamodb" % awsSdk2Version
1919
val awsEc2 = "com.amazonaws" % "aws-java-sdk-ec2" % awsVersion
2020
val awsKinesis = "com.amazonaws" % "aws-java-sdk-kinesis" % awsVersion
21-
val awsS3 = "com.amazonaws" % "aws-java-sdk-s3" % awsVersion
21+
val awsS3 = "software.amazon.awssdk" % "s3" % awsSdk2Version
2222
val eTagCachingS3 = "com.gu.etag-caching" %% "aws-s3-sdk-v2" % "7.0.0"
2323
val awsSes = "com.amazonaws" % "aws-java-sdk-ses" % awsVersion
2424
val awsSns = "com.amazonaws" % "aws-java-sdk-sns" % awsVersion

0 commit comments

Comments
 (0)