From 781814027808ef922acc069ed27f568b48a8ff08 Mon Sep 17 00:00:00 2001 From: Wai Sing Yiu Date: Fri, 10 Nov 2023 16:47:56 +0000 Subject: [PATCH 1/2] Bump simple-configuration to 1.5.7 --- build.sbt | 4 +-- .../scala/utils/CustomApplicationLoader.scala | 14 +++++++--- .../FakeBreakingNewsLambda.scala | 18 ++++++++++--- .../football/Configuration.scala | 27 ++++++++++++------- .../notifications/worker/Configuration.scala | 15 ++++++++--- .../gu/notifications/extractor/Lambda.scala | 13 +++++++-- .../ProcessNotificationScheduleLambda.scala | 14 ++++++++-- .../external/SsmConfig.scala | 18 ++++++++++--- 8 files changed, 96 insertions(+), 27 deletions(-) diff --git a/build.sbt b/build.sbt index bfe711072..424138830 100644 --- a/build.sbt +++ b/build.sbt @@ -30,7 +30,7 @@ val apacheThrift: String = "0.15.0" val jacksonDatabind: String = "2.15.3" val jacksonCbor: String = "2.15.3" val jacksonScalaModule: String = "2.15.3" -val simpleConfigurationVersion: String = "1.5.6" +val simpleConfigurationVersion: String = "1.5.7" val googleOAuthClient: String = "1.34.1" val nettyVersion: String = "4.1.100.Final" val slf4jVersion: String = "1.7.36" @@ -100,7 +100,7 @@ lazy val common = project "org.tpolecat" %% "doobie-specs2" % doobieVersion % Test, "org.tpolecat" %% "doobie-scalatest" % doobieVersion % Test, "org.tpolecat" %% "doobie-h2" % doobieVersion % Test, - "com.gu" %% "mobile-logstash-encoder" % "1.1.6", + "com.gu" %% "mobile-logstash-encoder" % "1.1.7", "com.gu" %% "simple-configuration-ssm" % simpleConfigurationVersion, "io.netty" % "netty-handler" % nettyVersion, "io.netty" % "netty-codec" % nettyVersion, diff --git a/common/src/main/scala/utils/CustomApplicationLoader.scala b/common/src/main/scala/utils/CustomApplicationLoader.scala index 64e465f08..f7ebea7a8 100644 --- a/common/src/main/scala/utils/CustomApplicationLoader.scala +++ b/common/src/main/scala/utils/CustomApplicationLoader.scala @@ -2,11 +2,12 @@ package utils import com.amazonaws.auth.profile.ProfileCredentialsProvider import com.amazonaws.auth.{AWSCredentialsProviderChain, InstanceProfileCredentialsProvider} -import com.gu.{AppIdentity, AwsIdentity} +import com.gu.{AppIdentity, AwsIdentity, DevIdentity} import com.gu.conf.{ConfigurationLoader, SSMConfigurationLocation} import play.api.ApplicationLoader.Context import play.api._ import software.amazon.awssdk.auth.credentials.{AwsCredentialsProviderChain => AwsCredentialsProviderChainV2, DefaultCredentialsProvider => DefaultCredentialsProviderV2, ProfileCredentialsProvider => ProfileCredentialsProviderV2} +import software.amazon.awssdk.regions.Region.EU_WEST_1 abstract class CustomApplicationLoader extends ApplicationLoader { def buildComponents(identity: AppIdentity, context: Context): BuiltInComponents @@ -23,9 +24,16 @@ abstract class CustomApplicationLoader extends ApplicationLoader { override def load(context: Context): Application = { LoggerConfigurator(context.environment.classLoader) foreach { _.configure(context.environment) } - val identity = AppIdentity.whoAmI("notifications") + val defaultAppName = "notifications" + val identity = Option(System.getenv("MOBILE_LOCAL_DEV")) match { + case Some(_) => DevIdentity(defaultAppName) + case None => + AppIdentity + .whoAmI(defaultAppName, credentialsv2) + .getOrElse(DevIdentity(defaultAppName)) + } val config = ConfigurationLoader.load(identity, credentialsv2) { - case AwsIdentity(app, stack, stage, _) => SSMConfigurationLocation(s"/notifications/$stage/$stack") + case AwsIdentity(app, stack, stage, region) => SSMConfigurationLocation(s"/notifications/$stage/$stack", region) } val loadedConfig = Configuration(config) val newContext = context.copy(initialConfiguration = loadedConfig.withFallback(context.initialConfiguration)) diff --git a/fakebreakingnewslambda/src/main/scala/fakebreakingnews/FakeBreakingNewsLambda.scala b/fakebreakingnewslambda/src/main/scala/fakebreakingnews/FakeBreakingNewsLambda.scala index 7cbf7f632..147be53a2 100644 --- a/fakebreakingnewslambda/src/main/scala/fakebreakingnews/FakeBreakingNewsLambda.scala +++ b/fakebreakingnewslambda/src/main/scala/fakebreakingnews/FakeBreakingNewsLambda.scala @@ -8,17 +8,29 @@ import models.{Android, Ios} import okhttp3.OkHttpClient import org.slf4j.{Logger, LoggerFactory} import com.gu.conf.{ConfigurationLoader, SSMConfigurationLocation} -import com.gu.{AppIdentity, AwsIdentity} +import com.gu.{AppIdentity, AwsIdentity, DevIdentity} import scala.concurrent.{Await, Future} import scala.concurrent.duration.Duration +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider +import software.amazon.awssdk.regions.Region.EU_WEST_1 class FakeBreakingNewsLambda { val iosUuid = UUID.fromString("3bf283d8-35f3-48e6-b377-b862c3f030e3") val androidUuid = UUID.fromString("a9b4c7cd-1713-4a56-9ada-aa4279dcf534") import scala.concurrent.ExecutionContext.Implicits.global private val logger: Logger = LoggerFactory.getLogger(this.getClass) - private val config: Config = ConfigurationLoader.load(AppIdentity.whoAmI(defaultAppName = "fake-breaking-news")) { - case AwsIdentity(_, _, stage, _) => SSMConfigurationLocation(s"/notifications/$stage/fakebreakingnews") + private def getIdentity(defaultAppName: String): AppIdentity = { + Option(System.getenv("MOBILE_LOCAL_DEV")) match { + case Some(_) => DevIdentity(defaultAppName) + case None => + AppIdentity + .whoAmI(defaultAppName, DefaultCredentialsProvider.builder().build()) + .getOrElse(DevIdentity(defaultAppName)) + } + } + private val config: Config = ConfigurationLoader.load(getIdentity(defaultAppName = "fake-breaking-news")) { + case AwsIdentity(_, _, stage, region) => + SSMConfigurationLocation(s"/notifications/$stage/fakebreakingnews", region) } val okhttp: OkHttpClient = new OkHttpClient() val client = new NotificationClient( diff --git a/football/src/main/scala/com/gu/mobile/notifications/football/Configuration.scala b/football/src/main/scala/com/gu/mobile/notifications/football/Configuration.scala index 7308511cb..265d51618 100644 --- a/football/src/main/scala/com/gu/mobile/notifications/football/Configuration.scala +++ b/football/src/main/scala/com/gu/mobile/notifications/football/Configuration.scala @@ -2,10 +2,12 @@ package com.gu.mobile.notifications.football import com.amazonaws.auth.profile.ProfileCredentialsProvider import com.amazonaws.auth.{AWSCredentialsProviderChain, DefaultAWSCredentialsProviderChain} -import com.gu.{AppIdentity, AwsIdentity} +import com.gu.{AppIdentity, AwsIdentity, DevIdentity} import com.typesafe.config.Config import software.amazon.awssdk.auth.credentials.{AwsCredentialsProviderChain => AwsCredentialsProviderChainV2, DefaultCredentialsProvider => DefaultCredentialsProviderV2, ProfileCredentialsProvider => ProfileCredentialsProviderV2} import com.gu.conf.{ConfigurationLoader, SSMConfigurationLocation} +import software.amazon.awssdk.regions.Region.EU_WEST_1 + class Configuration extends Logging { val credentials = new AWSCredentialsProviderChain( @@ -22,14 +24,21 @@ class Configuration extends Logging { val stage = Option(System.getenv("Stage")).getOrElse(sys.error("No app name set. Lambda will not run")) private val conf: Config = { - val identity = AppIdentity.whoAmI(defaultAppName = appName) - logger.info(s"Tryling: ${identity}") - ConfigurationLoader.load(identity = identity, credentials = credentialsv2) { - case AwsIdentity(app, stack, stage, _) => - val path = s"/$app/$stage/$stack" - logger.info(s"Attempting to retrieve config from: $path") - SSMConfigurationLocation(path = path) - } + val identity = Option(System.getenv("MOBILE_LOCAL_DEV")) match { + case Some(_) => DevIdentity(appName) + case None => + AppIdentity + .whoAmI(defaultAppName = appName, credentialsv2) + .getOrElse(DevIdentity(appName)) + } + + logger.info(s"Detected AppIdentity: ${identity}") + ConfigurationLoader.load(identity = identity, credentials = credentialsv2) { + case AwsIdentity(app, stack, stage, region) => + val path = s"/$app/$stage/$stack" + logger.info(s"Attempting to retrieve config from: $path") + SSMConfigurationLocation(path = path, region) + } } val paApiKey = conf.getString("pa.api-key") diff --git a/notificationworkerlambda/src/main/scala/com/gu/notifications/worker/Configuration.scala b/notificationworkerlambda/src/main/scala/com/gu/notifications/worker/Configuration.scala index 7c14d31d2..7fe8a284e 100644 --- a/notificationworkerlambda/src/main/scala/com/gu/notifications/worker/Configuration.scala +++ b/notificationworkerlambda/src/main/scala/com/gu/notifications/worker/Configuration.scala @@ -5,10 +5,12 @@ import com.typesafe.config.Config import db.JdbcConfig import com.gu.notifications.worker.delivery.fcm.models.FcmConfig import _root_.models.{Android, AndroidBeta, AndroidEdition, Ios, IosEdition, Platform} -import com.gu.{AppIdentity, AwsIdentity} +import com.gu.{AppIdentity, AwsIdentity, DevIdentity} import com.gu.conf.{ConfigurationLoader, SSMConfigurationLocation} import scala.jdk.CollectionConverters.CollectionHasAsScala +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider +import software.amazon.awssdk.regions.Region.EU_WEST_1 case class HarvesterConfiguration( jdbcConfig: JdbcConfig, @@ -48,9 +50,16 @@ case class TopicCountsConfiguration ( object Configuration { private def fetchConfiguration(workerName: String): Config = { - val identity = AppIdentity.whoAmI(defaultAppName = "notification-worker") + val defaultAppName = "notification-worker" + val identity = Option(System.getenv("MOBILE_LOCAL_DEV")) match { + case Some(_) => DevIdentity(defaultAppName) + case None => + AppIdentity + .whoAmI(defaultAppName, DefaultCredentialsProvider.builder().build()) + .getOrElse(DevIdentity(defaultAppName)) + } ConfigurationLoader.load(identity) { - case AwsIdentity(_, _, stage, _) => SSMConfigurationLocation(s"/notifications/$stage/workers/$workerName") + case AwsIdentity(_, _, stage, region) => SSMConfigurationLocation(s"/notifications/$stage/workers/$workerName", region) } } diff --git a/reportextractor/src/main/scala/com/gu/notifications/extractor/Lambda.scala b/reportextractor/src/main/scala/com/gu/notifications/extractor/Lambda.scala index 5b0af6c95..50e31dce2 100644 --- a/reportextractor/src/main/scala/com/gu/notifications/extractor/Lambda.scala +++ b/reportextractor/src/main/scala/com/gu/notifications/extractor/Lambda.scala @@ -12,7 +12,7 @@ import com.amazonaws.services.dynamodbv2.model._ import com.amazonaws.services.lambda.runtime.{Context, RequestHandler} import com.amazonaws.services.s3.AmazonS3ClientBuilder import com.amazonaws.services.s3.model.{CannedAccessControlList, ObjectMetadata, PutObjectRequest} -import com.gu.{AppIdentity, AwsIdentity} +import com.gu.{AppIdentity, AwsIdentity, DevIdentity} import models.NotificationType import org.slf4j.{Logger, LoggerFactory} import play.api.libs.json.{JsValue, Json} @@ -38,7 +38,16 @@ class Lambda extends RequestHandler[DateRange, Unit] { val credentials = new MobileAwsCredentialsProvider() - val identity: AppIdentity = AppIdentity.whoAmI(defaultAppName = "report-extractor", credentials = MobileAwsCredentialsProvider.mobileAwsCredentialsProviderv2) + val defaultAppName = "report-extractor" + + val identity: AppIdentity = + Option(System.getenv("MOBILE_LOCAL_DEV")) match { + case Some(_) => DevIdentity(defaultAppName) + case None => + AppIdentity + .whoAmI(defaultAppName, MobileAwsCredentialsProvider.mobileAwsCredentialsProviderv2) + .getOrElse(DevIdentity(defaultAppName)) + } val region: Regions = identity match { case AwsIdentity(_, _, _, region) => Regions.fromName(region) diff --git a/schedulelambda/src/main/scala/com/gu/notificationschedule/ProcessNotificationScheduleLambda.scala b/schedulelambda/src/main/scala/com/gu/notificationschedule/ProcessNotificationScheduleLambda.scala index 1f3ed1d83..f5ac038d1 100644 --- a/schedulelambda/src/main/scala/com/gu/notificationschedule/ProcessNotificationScheduleLambda.scala +++ b/schedulelambda/src/main/scala/com/gu/notificationschedule/ProcessNotificationScheduleLambda.scala @@ -4,7 +4,7 @@ import java.time.{Clock, Instant} import com.amazonaws.services.cloudwatch.AmazonCloudWatchAsyncClientBuilder import com.amazonaws.services.cloudwatch.model.StandardUnit import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsyncClientBuilder -import com.gu.{AppIdentity, AwsIdentity} +import com.gu.{AppIdentity, AwsIdentity, DevIdentity} import com.gu.notificationschedule.ProcessNotificationScheduleLambda.{lambdaClock, lambdaCloudWatch, lambdaConfig, lambdaOkHttpClient} import com.gu.notificationschedule.cloudwatch.{CloudWatch, CloudWatchImpl} import com.gu.notificationschedule.dynamo.{NotificationSchedulePersistenceImpl, NotificationSchedulePersistenceSync, NotificationsScheduleEntry} @@ -15,6 +15,7 @@ import org.slf4j.{Logger, LoggerFactory} import scala.concurrent.ExecutionContext import scala.util.{Failure, Success, Try} +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider class NotificationScheduleConfig(ssmConfig: SsmConfig) { @@ -26,8 +27,17 @@ class NotificationScheduleConfig(ssmConfig: SsmConfig) { object ProcessNotificationScheduleLambda { + private def getIdentity(defaultAppName: String): AppIdentity = { + Option(System.getenv("MOBILE_LOCAL_DEV")) match { + case Some(_) => DevIdentity(defaultAppName) + case None => + AppIdentity + .whoAmI(defaultAppName, DefaultCredentialsProvider.builder().build()) + .getOrElse(DevIdentity(defaultAppName)) + } + } private lazy val lambdaOkHttpClient = new OkHttpClient.Builder().build() - private lazy val lambdaConfig = AppIdentity.whoAmI(defaultAppName = "mobile-notifications-schedule") match { + private lazy val lambdaConfig = getIdentity(defaultAppName = "mobile-notifications-schedule") match { case _: AwsIdentity => new NotificationScheduleConfig(SsmConfigLoader.load()) case _ => throw new IllegalStateException("Not in aws") } diff --git a/schedulelambda/src/main/scala/com/gu/notificationschedule/external/SsmConfig.scala b/schedulelambda/src/main/scala/com/gu/notificationschedule/external/SsmConfig.scala index e6661abf6..7c3d033e1 100644 --- a/schedulelambda/src/main/scala/com/gu/notificationschedule/external/SsmConfig.scala +++ b/schedulelambda/src/main/scala/com/gu/notificationschedule/external/SsmConfig.scala @@ -1,11 +1,13 @@ package com.gu.notificationschedule.external -import com.gu.{AppIdentity, AwsIdentity} +import com.gu.{AppIdentity, AwsIdentity, DevIdentity} import com.gu.conf.{ConfigurationLoader, SSMConfigurationLocation} import com.typesafe.config.Config import org.slf4j.LoggerFactory import scala.util.Try +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider +import software.amazon.awssdk.regions.Region.EU_WEST_1 case class SsmConfig( app: String, @@ -16,11 +18,21 @@ case class SsmConfig( object SsmConfigLoader { - def load(awsIdentitySupplier: () => AppIdentity = () => AppIdentity.whoAmI(defaultAppName = "schedule")): SsmConfig = { + private def getIdentity(defaultAppName: String): AppIdentity = { + Option(System.getenv("MOBILE_LOCAL_DEV")) match { + case Some(_) => DevIdentity(defaultAppName) + case None => + AppIdentity + .whoAmI(defaultAppName, DefaultCredentialsProvider.builder().build()) + .getOrElse(DevIdentity(defaultAppName)) + } + } + + def load(awsIdentitySupplier: () => AppIdentity = () => getIdentity(defaultAppName = "schedule")): SsmConfig = { Try { val identity: AppIdentity = awsIdentitySupplier() val config: Config = ConfigurationLoader.load(identity) { - case identity: AwsIdentity => SSMConfigurationLocation(s"/notifications/${identity.stage}/${identity.stack}") + case identity: AwsIdentity => SSMConfigurationLocation(s"/notifications/${identity.stage}/${identity.stack}", identity.region) } identity match { case awsIdentity: AwsIdentity => SsmConfig(awsIdentity.app, awsIdentity.stack, awsIdentity.stage, config) From d0ab07a44663bbf01a0fdb536f450be3e69ac64c Mon Sep 17 00:00:00 2001 From: Wai Sing Yiu Date: Mon, 13 Nov 2023 10:14:14 +0000 Subject: [PATCH 2/2] Pin simple-configuration to 1.5.7 --- .scala-steward.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.scala-steward.conf b/.scala-steward.conf index f3a4d4f6d..b1c0a17a9 100644 --- a/.scala-steward.conf +++ b/.scala-steward.conf @@ -14,8 +14,8 @@ updates.pin = [ { groupId = "org.scanamo", artifactId="scanamo-testkit", version = "1.0.0-M12-1" }, # A separate task to bump simple-configuration - { groupId = "com.gu", artifactId = "simple-configuration-ssm", version = "1.5.6" }, - { groupId = "com.gu", artifactId = "simple-configuration-core", version = "1.5.6" }, + { groupId = "com.gu", artifactId = "simple-configuration-ssm", version = "1.5.7" }, + { groupId = "com.gu", artifactId = "simple-configuration-core", version = "1.5.7" }, # A separate task to bump slf4j from version 1 to version 2 { groupId = "org.slf4j", artifactId = "slf4j-api", version = "1.7.36" },