From 45032ac1009bfc7bb3903a42b86607ea3d14dc11 Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Fri, 24 Jun 2022 20:26:08 +0000 Subject: [PATCH 1/5] Update http4s-circe, http4s-client, ... to 0.23.13 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0d67bc4c..a68a3fc5 100644 --- a/build.sbt +++ b/build.sbt @@ -59,7 +59,7 @@ ThisBuild / crossScalaVersions := Seq(Scala212, Scala3, Scala213) val catsEffectVersion = "3.3.12" val circeVersion = "0.14.2" val fs2Version = "3.2.8" -val http4sVersion = "0.23.12" +val http4sVersion = "0.23.13" val natchezVersion = "0.1.6" val munitVersion = "0.7.29" val munitCEVersion = "1.0.7" From dcf315dc0e746cd6109b12f7438fb1e81bf4b8d3 Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Sat, 25 Jun 2022 16:34:11 +0000 Subject: [PATCH 2/5] Update sbt-scalajs, scalajs-compiler, ... to 1.10.1 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 963131b9..ae69f51f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,3 @@ addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.4.12") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.0") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.1") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0") From 5c30a4e4963012b92586ff9a9ef09e46d33a904d Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 20:31:58 +0000 Subject: [PATCH 3/5] Update cats-effect to 3.3.13 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a68a3fc5..9552dfd3 100644 --- a/build.sbt +++ b/build.sbt @@ -56,7 +56,7 @@ val Scala213 = "2.13.8" val Scala3 = "3.1.3" ThisBuild / crossScalaVersions := Seq(Scala212, Scala3, Scala213) -val catsEffectVersion = "3.3.12" +val catsEffectVersion = "3.3.13" val circeVersion = "0.14.2" val fs2Version = "3.2.8" val http4sVersion = "0.23.13" From c6c6edd71f5017681a60a154628c897f23edaa3a Mon Sep 17 00:00:00 2001 From: "typelevel-steward[bot]" <106827141+typelevel-steward[bot]@users.noreply.github.com> Date: Fri, 1 Jul 2022 20:27:56 +0000 Subject: [PATCH 4/5] Update fs2-io to 3.2.9 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9552dfd3..4eed3583 100644 --- a/build.sbt +++ b/build.sbt @@ -58,7 +58,7 @@ ThisBuild / crossScalaVersions := Seq(Scala212, Scala3, Scala213) val catsEffectVersion = "3.3.13" val circeVersion = "0.14.2" -val fs2Version = "3.2.8" +val fs2Version = "3.2.9" val http4sVersion = "0.23.13" val natchezVersion = "0.1.6" val munitVersion = "0.7.29" From 7b24b821413e13c527df61d16f53a7b91980a841 Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Tue, 5 Jul 2022 17:35:07 -0500 Subject: [PATCH 5/5] add PhysicalResourceId to CloudFormation Custom Resource interface, where appropriate PhysicalResourceId is "always sent with Update and Delete requests; never sent with Create" (according to AWS docs) and is commonly required to actually perform the work needed to do an update or delete of the resource. This PR encodes that contract and makes life a bit easier for developers implementing update/delete, since they won't have to deal with the optionality of the value in the event encoding. --- .../CloudFormationCustomResource.scala | 18 +++++++----- .../feral/lambda/cloudformation/package.scala | 4 ++- ...udFormationCustomResourceArbitraries.scala | 4 +-- .../ResponseSerializationSuite.scala | 29 +++++++++++++------ 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/CloudFormationCustomResource.scala b/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/CloudFormationCustomResource.scala index 9bfa3bc3..e9488b88 100644 --- a/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/CloudFormationCustomResource.scala +++ b/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/CloudFormationCustomResource.scala @@ -30,8 +30,12 @@ import org.http4s.client.dsl.Http4sClientDsl trait CloudFormationCustomResource[F[_], Input, Output] { def createResource(input: Input): F[HandlerResponse[Output]] - def updateResource(input: Input): F[HandlerResponse[Output]] - def deleteResource(input: Input): F[HandlerResponse[Output]] + def updateResource( + input: Input, + physicalResourceId: PhysicalResourceId): F[HandlerResponse[Output]] + def deleteResource( + input: Input, + physicalResourceId: PhysicalResourceId): F[HandlerResponse[Output]] } object CloudFormationCustomResource { @@ -47,11 +51,11 @@ object CloudFormationCustomResource { import http4sClientDsl._ env.event.flatMap { event => - (event.RequestType match { - case CreateRequest => handler.createResource(event.ResourceProperties) - case UpdateRequest => handler.updateResource(event.ResourceProperties) - case DeleteRequest => handler.deleteResource(event.ResourceProperties) - case OtherRequestType(other) => illegalRequestType(other) + ((event.RequestType, event.PhysicalResourceId) match { + case (CreateRequest, None) => handler.createResource(event.ResourceProperties) + case (UpdateRequest, Some(id)) => handler.updateResource(event.ResourceProperties, id) + case (DeleteRequest, Some(id)) => handler.deleteResource(event.ResourceProperties, id) + case (other, _) => illegalRequestType(other.toString) }).attempt .map(_.fold(exceptionResponse(event)(_), successResponse(event)(_))) .flatMap { resp => client.successful(PUT(resp.asJson, event.ResponseURL)) } diff --git a/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/package.scala b/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/package.scala index 31c933d9..d9081bc8 100644 --- a/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/package.scala +++ b/lambda-cloudformation-custom-resource/src/main/scala/feral/lambda/cloudformation/package.scala @@ -72,7 +72,9 @@ package cloudformation { case object CreateRequest extends CloudFormationRequestType case object UpdateRequest extends CloudFormationRequestType case object DeleteRequest extends CloudFormationRequestType - final case class OtherRequestType(requestType: String) extends CloudFormationRequestType + final case class OtherRequestType(requestType: String) extends CloudFormationRequestType { + override def toString: String = requestType + } implicit val encoder: Encoder[CloudFormationRequestType] = { case CreateRequest => "Create".asJson diff --git a/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/CloudFormationCustomResourceArbitraries.scala b/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/CloudFormationCustomResourceArbitraries.scala index 95d5405c..59ad4502 100644 --- a/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/CloudFormationCustomResourceArbitraries.scala +++ b/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/CloudFormationCustomResourceArbitraries.scala @@ -165,7 +165,7 @@ trait CloudFormationCustomResourceArbitraries { requestId <- arbitrary[RequestId] resourceType <- arbitrary[ResourceType] logicalResourceId <- arbitrary[LogicalResourceId] - physicalResourceId <- arbitrary[Option[PhysicalResourceId]] + physicalResourceId <- arbitrary[PhysicalResourceId] resourceProperties <- arbitrary[A] oldResourceProperties <- arbitrary[Option[JsonObject]] } yield CloudFormationCustomResourceRequest( @@ -175,7 +175,7 @@ trait CloudFormationCustomResourceArbitraries { requestId, resourceType, logicalResourceId, - physicalResourceId, + if (requestType == CreateRequest) None else physicalResourceId.some, resourceProperties, oldResourceProperties ) diff --git a/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/ResponseSerializationSuite.scala b/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/ResponseSerializationSuite.scala index b4cd54c2..8033548d 100644 --- a/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/ResponseSerializationSuite.scala +++ b/lambda-cloudformation-custom-resource/src/test/scala/feral/lambda/cloudformation/ResponseSerializationSuite.scala @@ -83,7 +83,7 @@ class ResponseSerializationSuite } ) .deepDropNullValues - case _ => + case CreateRequest => Json.obj( "Status" -> "SUCCESS".asJson, "PhysicalResourceId" -> convertInputToFakePhysicalResourceId( @@ -93,6 +93,15 @@ class ResponseSerializationSuite "LogicalResourceId" -> event.LogicalResourceId.asJson, "Data" -> event.RequestType.asJson ) + case UpdateRequest | DeleteRequest => + Json.obj( + "Status" -> "SUCCESS".asJson, + "PhysicalResourceId" -> event.PhysicalResourceId.get.asJson, + "StackId" -> event.StackId.asJson, + "RequestId" -> event.RequestId.asJson, + "LogicalResourceId" -> event.LogicalResourceId.asJson, + "Data" -> event.RequestType.asJson + ) } expect(body eqv expectedJson) @@ -142,14 +151,16 @@ object ResponseSerializationSuite { convertInputToFakePhysicalResourceId(input), CreateRequest.some.widen[CloudFormationRequestType]).pure[F] - override def updateResource(input: String): F[HandlerResponse[CloudFormationRequestType]] = - HandlerResponse( - convertInputToFakePhysicalResourceId(input), - UpdateRequest.some.widen[CloudFormationRequestType]).pure[F] + override def updateResource( + input: String, + physicalResourceId: PhysicalResourceId): F[HandlerResponse[CloudFormationRequestType]] = + HandlerResponse(physicalResourceId, UpdateRequest.some.widen[CloudFormationRequestType]) + .pure[F] - override def deleteResource(input: String): F[HandlerResponse[CloudFormationRequestType]] = - HandlerResponse( - convertInputToFakePhysicalResourceId(input), - DeleteRequest.some.widen[CloudFormationRequestType]).pure[F] + override def deleteResource( + input: String, + physicalResourceId: PhysicalResourceId): F[HandlerResponse[CloudFormationRequestType]] = + HandlerResponse(physicalResourceId, DeleteRequest.some.widen[CloudFormationRequestType]) + .pure[F] } }