From 1837af8c608c5fab36715b2b91b08b422ec5353d Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Thu, 25 Jul 2024 11:11:14 -0400 Subject: [PATCH 1/8] feat: allow configurable choice of annotations for rolling update revision --- .gitignore | 3 ++ .../src/main/resources/reference.conf | 5 +++ .../kubernetes/KubernetesApiImpl.scala | 5 ++- .../kubernetes/KubernetesJsonSupport.scala | 39 ++++++++++++++++++- .../kubernetes/KubernetesSettings.scala | 18 +++++++-- 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index cc2ca53ee..4203b455a 100755 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ target/ # attachments created by scripts/prepare-downloads.sh docs/src/main/paradox/attachments + +# Metals detritus +project/project diff --git a/rolling-update-kubernetes/src/main/resources/reference.conf b/rolling-update-kubernetes/src/main/resources/reference.conf index 02afd824e..134a7b223 100644 --- a/rolling-update-kubernetes/src/main/resources/reference.conf +++ b/rolling-update-kubernetes/src/main/resources/reference.conf @@ -34,6 +34,11 @@ akka.rollingupdate.kubernetes { pod-name = "" pod-name = ${?KUBERNETES_POD_NAME} + # Annotations to check to determine the revision. The first one in the list which matches + # wins. The default is suitable for "vanilla" Kubernetes Deployments, but other CI/CD systems + # may set a different annotation. + revision-annotation = [ "deployment.kubernetes.io/revision" ] + secure-api-server = true # Configuration for the Pod Deletion Cost extension diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala index 32d9d02a9..4860f0028 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala @@ -55,6 +55,8 @@ import scala.util.control.NonFatal import system.dispatcher + override val _revisionAnnotations = settings + private implicit val sys: ActorSystem = system private val log = Logging(system, classOf[KubernetesApiImpl]) private val http = Http()(system) @@ -93,6 +95,7 @@ import scala.util.control.NonFatal case HttpResponse(status, _, e, _) => e.discardBytes() throw new PodCostException(s"Request failed with status=$status") + // Can we make this exhaustive? } } @@ -213,7 +216,7 @@ PUTs must contain resourceVersions. Response: case None => Future.failed(new ReadRevisionException("No replica name found")) } - val revision = replicaSet.map(_.metadata.annotations.`deployment.kubernetes.io/revision`) + val revision = replicaSet.map(_.metadata.annotations.revision) revision.map(Some(_)).recoverWith { case ex => if (tries >= maxTries) { diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala index cb929c3e8..64fdbcc19 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala @@ -10,13 +10,16 @@ import akka.annotation.InternalApi import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import spray.json.DefaultJsonProtocol import spray.json.JsonFormat +import spray.json.JsObject import spray.json.RootJsonFormat +import spray.json.JsString +import spray.json.JsValue /** * INTERNAL API */ @InternalApi -case class ReplicaAnnotation(`deployment.kubernetes.io/revision`: String) +case class ReplicaAnnotation(revision: String, source: String, otherAnnotations: Map[String, JsValue]) /** * INTERNAL API @@ -75,6 +78,10 @@ case class Spec(pods: immutable.Seq[PodCost]) */ @InternalApi trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { + val _revisionAnnotations: HasRevisionAnnotations = new HasRevisionAnnotations { + def revisionAnnotations = Seq("deployment.kubernetes.io/revision") + } + // If adding more formats here, remember to also add in META-INF/native-image reflect config implicit val metadataFormat: JsonFormat[Metadata] = jsonFormat2(Metadata.apply) implicit val podCostFormat: JsonFormat[PodCost] = jsonFormat5(PodCost.apply) @@ -86,7 +93,35 @@ trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { implicit val podMetadataFormat: JsonFormat[PodMetadata] = jsonFormat1(PodMetadata.apply) implicit val podFormat: RootJsonFormat[Pod] = jsonFormat1(Pod.apply) - implicit val replicaAnnotationFormat: JsonFormat[ReplicaAnnotation] = jsonFormat1(ReplicaAnnotation.apply) + implicit val replicaAnnotationFormat: RootJsonFormat[ReplicaAnnotation] = + new RootJsonFormat[ReplicaAnnotation] { + // Not sure if we ever write this out, but if we do, this will let us write out exactly what we took in + def write(ra: ReplicaAnnotation): JsValue = + if (ra.revision.nonEmpty && ra.source.nonEmpty) { + JsObject(ra.otherAnnotations + (ra.source -> JsString(ra.revision))) + } else JsObject(ra.otherAnnotations) + + def read(json: JsValue): ReplicaAnnotation = { + json match { + case JsObject(fields) => + _revisionAnnotations.revisionAnnotations.find { annotation => + fields.get(annotation).exists(_.isInstanceOf[JsString]) + } match { + case Some(winningAnnotation) => + ReplicaAnnotation( + fields(winningAnnotation).asInstanceOf[JsString].value, + winningAnnotation, + fields - winningAnnotation) + + case None => + ReplicaAnnotation("", "", fields) + } + + case _ => spray.json.deserializationError("expected an object") + } + } + } + implicit val replicaSetMedatataFormat: JsonFormat[ReplicaSetMetadata] = jsonFormat1(ReplicaSetMetadata.apply) implicit val podReplicaSetFormat: RootJsonFormat[ReplicaSet] = jsonFormat1(ReplicaSet.apply) } diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala index f00fdfb2c..706fdf0f2 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala @@ -4,11 +4,13 @@ package akka.rollingupdate.kubernetes -import scala.concurrent.duration._ import akka.util.JavaDurationConverters._ import akka.annotation.InternalApi import com.typesafe.config.Config +import scala.concurrent.duration._ +import scala.jdk.CollectionConverters.ListHasAsScala + /** * INTERNAL API */ @@ -47,7 +49,8 @@ private[kubernetes] object KubernetesSettings { config.getString("pod-name"), config.getBoolean("secure-api-server"), config.getDuration("api-service-request-timeout").asScala, - customResourceSettings + customResourceSettings, + config.getStringList("revision-annotation").asScala.toList ) } } @@ -67,8 +70,17 @@ private[kubernetes] class KubernetesSettings( val secure: Boolean, val apiServiceRequestTimeout: FiniteDuration, val customResourceSettings: CustomResourceSettings, + val revisionAnnotations: Seq[String], val bodyReadTimeout: FiniteDuration = 1.second -) +) extends HasRevisionAnnotations + +/** + * INTERNAL API + */ +@InternalApi +private[kubernetes] trait HasRevisionAnnotations { + def revisionAnnotations: Seq[String] +} /** * INTERNAL API From 6eb7b8aeed547078c1aa0acdd2bdcd8f1eea7eac Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Thu, 25 Jul 2024 11:35:34 -0400 Subject: [PATCH 2/8] tests, style --- .../src/main/resources/reference.conf | 8 ++++---- .../kubernetes/KubernetesApiSpec.scala | 14 +++++++++++++- .../PodDeletionCostAnnotatorCrSpec.scala | 3 ++- .../kubernetes/PodDeletionCostAnnotatorSpec.scala | 3 ++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/rolling-update-kubernetes/src/main/resources/reference.conf b/rolling-update-kubernetes/src/main/resources/reference.conf index 134a7b223..639cf5cce 100644 --- a/rolling-update-kubernetes/src/main/resources/reference.conf +++ b/rolling-update-kubernetes/src/main/resources/reference.conf @@ -34,10 +34,10 @@ akka.rollingupdate.kubernetes { pod-name = "" pod-name = ${?KUBERNETES_POD_NAME} - # Annotations to check to determine the revision. The first one in the list which matches - # wins. The default is suitable for "vanilla" Kubernetes Deployments, but other CI/CD systems - # may set a different annotation. - revision-annotation = [ "deployment.kubernetes.io/revision" ] + # Annotations to check to determine the revision. The first one in the list which matches + # wins. The default is suitable for "vanilla" Kubernetes Deployments, but other CI/CD systems + # may set a different annotation. + revision-annotation = [ "deployment.kubernetes.io/revision" ] secure-api-server = true diff --git a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala index 3cf61e7f0..2508a36fc 100644 --- a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala +++ b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala @@ -83,7 +83,8 @@ class KubernetesApiSpec podName = podName, secure = false, apiServiceRequestTimeout = 2.seconds, - customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds) + customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds), + revisionAnnotations = Seq("custom.akka.io/revision", "deployment.kubernetes.io/revision") ) } @@ -167,6 +168,17 @@ class KubernetesApiSpec } } + "parse pod and replica responses to get the revision from custom annotations" in { + stubPodResponse() + stubReplicaResponse(defaultReplicaResponseJson.replaceAllLiterally("deployment.kubernetes.io", "custom.akka.io")) + + EventFilter + .info(pattern = "Reading revision from Kubernetes: akka.cluster.app-version was set to 1", occurrences = 1) + .intercept { + kubernetesApi.readRevision().futureValue should be("1") + } + } + "retry and then fail when pod not found" in { stubFor(getPod(podName1).willReturn(aResponse().withStatus(404))) EventFilter diff --git a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala index 473f0054a..234fb5086 100644 --- a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala +++ b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala @@ -115,7 +115,8 @@ class PodDeletionCostAnnotatorCrSpec podName = podName, secure = false, apiServiceRequestTimeout = 2.seconds, - customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds) + customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds), + revisionAnnotations = Seq("deployment.kubernetes.io/revision") ) } diff --git a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala index 4d40b57a2..dba4ee822 100644 --- a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala +++ b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala @@ -89,7 +89,8 @@ class PodDeletionCostAnnotatorSpec podName = podName, secure = false, apiServiceRequestTimeout = 2.seconds, - customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds) + customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds), + revisionAnnotations = Seq("deployment.kubernetes.io/revision") ) } From 8c7e7d1f9366bf3a6626cc7998a726decef6699a Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Thu, 25 Jul 2024 11:40:37 -0400 Subject: [PATCH 3/8] refine the default --- .../kubernetes/KubernetesJsonSupport.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala index 64fdbcc19..5db61bbe9 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala @@ -78,9 +78,7 @@ case class Spec(pods: immutable.Seq[PodCost]) */ @InternalApi trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { - val _revisionAnnotations: HasRevisionAnnotations = new HasRevisionAnnotations { - def revisionAnnotations = Seq("deployment.kubernetes.io/revision") - } + val _revisionAnnotations: HasRevisionAnnotations = KubernetesJsonSupport.defaultRevisionAnnotations // If adding more formats here, remember to also add in META-INF/native-image reflect config implicit val metadataFormat: JsonFormat[Metadata] = jsonFormat2(Metadata.apply) @@ -125,3 +123,9 @@ trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { implicit val replicaSetMedatataFormat: JsonFormat[ReplicaSetMetadata] = jsonFormat1(ReplicaSetMetadata.apply) implicit val podReplicaSetFormat: RootJsonFormat[ReplicaSet] = jsonFormat1(ReplicaSet.apply) } + +private[kubernetes] object KubernetesJsonSupport { + val defaultRevisionAnnotations: HasRevisionAnnotations = new HasRevisionAnnotations { + val revisionAnnotations = Seq("deployment.kubernetes.io/revision") + } +} From 23f54e6959f725a08730b3edfba54b8e4f0e4ada Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Thu, 25 Jul 2024 11:48:08 -0400 Subject: [PATCH 4/8] fix bad link in docs --- docs/src/main/paradox/rolling-updates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/main/paradox/rolling-updates.md b/docs/src/main/paradox/rolling-updates.md index b848074ad..decbc6de2 100644 --- a/docs/src/main/paradox/rolling-updates.md +++ b/docs/src/main/paradox/rolling-updates.md @@ -237,7 +237,7 @@ Java #### Configuration -The following configuration is required, more details for each and additional configurations can be found in [reference.conf](https://github.com/akka/akka-management/blob/main/rolling-updates-kubernetes/src/main/resources/reference.conf): +The following configuration is required, more details for each and additional configurations can be found in [reference.conf](https://github.com/akka/akka-management/blob/main/rolling-update-kubernetes/src/main/resources/reference.conf): * `akka.rollingupdate.kubernetes.pod-name`: this can be provided by setting `KUBERNETES_POD_NAME` environment variable to `metadata.name` on the Kubernetes container spec. From 220d106fa5997eea0b17738b0e8cb91a25ada5f7 Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Thu, 25 Jul 2024 11:54:04 -0400 Subject: [PATCH 5/8] does IT work, lol --- .gitignore | 5 +++-- .../kubernetes/KubernetesApiIntegrationTest.scala | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4203b455a..b00e62802 100755 --- a/.gitignore +++ b/.gitignore @@ -12,11 +12,12 @@ target/ *.class *.log -.metals .vscode # attachments created by scripts/prepare-downloads.sh docs/src/main/paradox/attachments # Metals detritus -project/project +.metals +metals.sbt +**/project/project diff --git a/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala b/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala index dcc0f5a88..fe3c52085 100644 --- a/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala +++ b/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala @@ -63,7 +63,8 @@ class KubernetesApiIntegrationTest enabled = true, crName = None, cleanupAfter = 60.seconds - ) + ), + revisionAnnotations = KubernetesJsonSupport.defaultRevisionAnnotations.revisionAnnotations ) private val underTest = From c1380d1ea69d79bc7fdf24c0217d783ab370800e Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Tue, 30 Jul 2024 11:51:51 -0400 Subject: [PATCH 6/8] and then there was only one... --- .../KubernetesApiIntegrationTest.scala | 2 +- .../src/main/resources/reference.conf | 7 ++--- .../kubernetes/KubernetesApiImpl.scala | 2 +- .../kubernetes/KubernetesJsonSupport.scala | 22 ++++++-------- .../kubernetes/KubernetesSettings.scala | 10 +++---- .../kubernetes/KubernetesApiSpec.scala | 29 +++++++++++++++++-- .../PodDeletionCostAnnotatorCrSpec.scala | 2 +- .../PodDeletionCostAnnotatorSpec.scala | 2 +- 8 files changed, 48 insertions(+), 28 deletions(-) diff --git a/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala b/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala index fe3c52085..1408fae79 100644 --- a/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala +++ b/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala @@ -64,7 +64,7 @@ class KubernetesApiIntegrationTest crName = None, cleanupAfter = 60.seconds ), - revisionAnnotations = KubernetesJsonSupport.defaultRevisionAnnotations.revisionAnnotations + revisionAnnotation = KubernetesJsonSupport.defaultRevisionAnnotation.revisionAnnotation ) private val underTest = diff --git a/rolling-update-kubernetes/src/main/resources/reference.conf b/rolling-update-kubernetes/src/main/resources/reference.conf index 639cf5cce..dba70c99f 100644 --- a/rolling-update-kubernetes/src/main/resources/reference.conf +++ b/rolling-update-kubernetes/src/main/resources/reference.conf @@ -34,10 +34,9 @@ akka.rollingupdate.kubernetes { pod-name = "" pod-name = ${?KUBERNETES_POD_NAME} - # Annotations to check to determine the revision. The first one in the list which matches - # wins. The default is suitable for "vanilla" Kubernetes Deployments, but other CI/CD systems - # may set a different annotation. - revision-annotation = [ "deployment.kubernetes.io/revision" ] + # Annotations to check to determine the revision. The default is suitable for "vanilla" + # Kubernetes Deployments, but other CI/CD systems may set a different annotation. + revision-annotation = "deployment.kubernetes.io/revision" secure-api-server = true diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala index 4860f0028..98b3ba4fd 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala @@ -55,7 +55,7 @@ import scala.util.control.NonFatal import system.dispatcher - override val _revisionAnnotations = settings + override val _revisionAnnotation: HasRevisionAnnotation = settings private implicit val sys: ActorSystem = system private val log = Logging(system, classOf[KubernetesApiImpl]) diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala index 5db61bbe9..79ecba7d7 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala @@ -78,7 +78,7 @@ case class Spec(pods: immutable.Seq[PodCost]) */ @InternalApi trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { - val _revisionAnnotations: HasRevisionAnnotations = KubernetesJsonSupport.defaultRevisionAnnotations + val _revisionAnnotation: HasRevisionAnnotation = KubernetesJsonSupport.defaultRevisionAnnotation // If adding more formats here, remember to also add in META-INF/native-image reflect config implicit val metadataFormat: JsonFormat[Metadata] = jsonFormat2(Metadata.apply) @@ -102,16 +102,12 @@ trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { def read(json: JsValue): ReplicaAnnotation = { json match { case JsObject(fields) => - _revisionAnnotations.revisionAnnotations.find { annotation => - fields.get(annotation).exists(_.isInstanceOf[JsString]) - } match { - case Some(winningAnnotation) => - ReplicaAnnotation( - fields(winningAnnotation).asInstanceOf[JsString].value, - winningAnnotation, - fields - winningAnnotation) - - case None => + val annotation = _revisionAnnotation.revisionAnnotation + fields.get(annotation) match { + case Some(JsString(foundRevision)) => + ReplicaAnnotation(foundRevision, annotation, fields - annotation) + + case _ => ReplicaAnnotation("", "", fields) } @@ -125,7 +121,7 @@ trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { } private[kubernetes] object KubernetesJsonSupport { - val defaultRevisionAnnotations: HasRevisionAnnotations = new HasRevisionAnnotations { - val revisionAnnotations = Seq("deployment.kubernetes.io/revision") + val defaultRevisionAnnotation: HasRevisionAnnotation = new HasRevisionAnnotation { + val revisionAnnotation = "deployment.kubernetes.io/revision" } } diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala index 706fdf0f2..56089afb9 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala @@ -50,7 +50,7 @@ private[kubernetes] object KubernetesSettings { config.getBoolean("secure-api-server"), config.getDuration("api-service-request-timeout").asScala, customResourceSettings, - config.getStringList("revision-annotation").asScala.toList + config.getString("revision-annotation") ) } } @@ -70,16 +70,16 @@ private[kubernetes] class KubernetesSettings( val secure: Boolean, val apiServiceRequestTimeout: FiniteDuration, val customResourceSettings: CustomResourceSettings, - val revisionAnnotations: Seq[String], + val revisionAnnotation: String, val bodyReadTimeout: FiniteDuration = 1.second -) extends HasRevisionAnnotations +) extends HasRevisionAnnotation /** * INTERNAL API */ @InternalApi -private[kubernetes] trait HasRevisionAnnotations { - def revisionAnnotations: Seq[String] +private[kubernetes] trait HasRevisionAnnotation { + def revisionAnnotation: String } /** diff --git a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala index 2508a36fc..ede2bcc65 100644 --- a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala +++ b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiSpec.scala @@ -84,7 +84,7 @@ class KubernetesApiSpec secure = false, apiServiceRequestTimeout = 2.seconds, customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds), - revisionAnnotations = Seq("custom.akka.io/revision", "deployment.kubernetes.io/revision") + revisionAnnotation = "deployment.kubernetes.io/revision" ) } @@ -172,10 +172,35 @@ class KubernetesApiSpec stubPodResponse() stubReplicaResponse(defaultReplicaResponseJson.replaceAllLiterally("deployment.kubernetes.io", "custom.akka.io")) + val customSettings = { + val base = settings(podName1) + new KubernetesSettings( + apiCaPath = base.apiCaPath, + apiTokenPath = base.apiTokenPath, + apiServiceHost = base.apiServiceHost, + apiServicePort = base.apiServicePort, + namespace = base.namespace, + namespacePath = base.namespacePath, + podName = base.podName, + secure = base.secure, + apiServiceRequestTimeout = base.apiServiceRequestTimeout, + customResourceSettings = base.customResourceSettings, + revisionAnnotation = "custom.akka.io/revision" + ) + } + + val customKubernetesApi = + new KubernetesApiImpl( + system, + customSettings, + namespace, + apiToken = "apiToken", + clientHttpsConnectionContext = None) + EventFilter .info(pattern = "Reading revision from Kubernetes: akka.cluster.app-version was set to 1", occurrences = 1) .intercept { - kubernetesApi.readRevision().futureValue should be("1") + customKubernetesApi.readRevision().futureValue should be("1") } } diff --git a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala index 234fb5086..3390c8ce1 100644 --- a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala +++ b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorCrSpec.scala @@ -116,7 +116,7 @@ class PodDeletionCostAnnotatorCrSpec secure = false, apiServiceRequestTimeout = 2.seconds, customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds), - revisionAnnotations = Seq("deployment.kubernetes.io/revision") + revisionAnnotation = "deployment.kubernetes.io/revision" ) } diff --git a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala index dba4ee822..f4080cf24 100644 --- a/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala +++ b/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/PodDeletionCostAnnotatorSpec.scala @@ -90,7 +90,7 @@ class PodDeletionCostAnnotatorSpec secure = false, apiServiceRequestTimeout = 2.seconds, customResourceSettings = new CustomResourceSettings(enabled = false, crName = None, 60.seconds), - revisionAnnotations = Seq("deployment.kubernetes.io/revision") + revisionAnnotation = "deployment.kubernetes.io/revision" ) } From bee11a8397009ca5349a5d0c643637edb9cad584 Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Wed, 31 Jul 2024 10:54:08 -0400 Subject: [PATCH 7/8] no more default annotation in code --- .../kubernetes/KubernetesApiIntegrationTest.scala | 2 +- .../kubernetes/KubernetesApiImpl.scala | 2 +- .../kubernetes/KubernetesJsonSupport.scala | 13 +++---------- .../kubernetes/KubernetesSettings.scala | 10 +--------- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala b/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala index 1408fae79..db5bb2d65 100644 --- a/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala +++ b/integration-test/rolling-update-kubernetes/src/test/scala/akka/rollingupdate/kubernetes/KubernetesApiIntegrationTest.scala @@ -64,7 +64,7 @@ class KubernetesApiIntegrationTest crName = None, cleanupAfter = 60.seconds ), - revisionAnnotation = KubernetesJsonSupport.defaultRevisionAnnotation.revisionAnnotation + revisionAnnotation = "deployment.kubernetes.io/revision" ) private val underTest = diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala index 98b3ba4fd..782608dae 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesApiImpl.scala @@ -55,7 +55,7 @@ import scala.util.control.NonFatal import system.dispatcher - override val _revisionAnnotation: HasRevisionAnnotation = settings + override val revisionAnnotation = settings.revisionAnnotation private implicit val sys: ActorSystem = system private val log = Logging(system, classOf[KubernetesApiImpl]) diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala index 79ecba7d7..b99296970 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesJsonSupport.scala @@ -78,7 +78,7 @@ case class Spec(pods: immutable.Seq[PodCost]) */ @InternalApi trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { - val _revisionAnnotation: HasRevisionAnnotation = KubernetesJsonSupport.defaultRevisionAnnotation + val revisionAnnotation: String // If adding more formats here, remember to also add in META-INF/native-image reflect config implicit val metadataFormat: JsonFormat[Metadata] = jsonFormat2(Metadata.apply) @@ -102,10 +102,9 @@ trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { def read(json: JsValue): ReplicaAnnotation = { json match { case JsObject(fields) => - val annotation = _revisionAnnotation.revisionAnnotation - fields.get(annotation) match { + fields.get(revisionAnnotation) match { case Some(JsString(foundRevision)) => - ReplicaAnnotation(foundRevision, annotation, fields - annotation) + ReplicaAnnotation(foundRevision, revisionAnnotation, fields - revisionAnnotation) case _ => ReplicaAnnotation("", "", fields) @@ -119,9 +118,3 @@ trait KubernetesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { implicit val replicaSetMedatataFormat: JsonFormat[ReplicaSetMetadata] = jsonFormat1(ReplicaSetMetadata.apply) implicit val podReplicaSetFormat: RootJsonFormat[ReplicaSet] = jsonFormat1(ReplicaSet.apply) } - -private[kubernetes] object KubernetesJsonSupport { - val defaultRevisionAnnotation: HasRevisionAnnotation = new HasRevisionAnnotation { - val revisionAnnotation = "deployment.kubernetes.io/revision" - } -} diff --git a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala index 56089afb9..bba987374 100644 --- a/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala +++ b/rolling-update-kubernetes/src/main/scala/akka/rollingupdate/kubernetes/KubernetesSettings.scala @@ -72,15 +72,7 @@ private[kubernetes] class KubernetesSettings( val customResourceSettings: CustomResourceSettings, val revisionAnnotation: String, val bodyReadTimeout: FiniteDuration = 1.second -) extends HasRevisionAnnotation - -/** - * INTERNAL API - */ -@InternalApi -private[kubernetes] trait HasRevisionAnnotation { - def revisionAnnotation: String -} +) /** * INTERNAL API From 2917be465b5418bbd24050f564cef03f77359949 Mon Sep 17 00:00:00 2001 From: Levi Ramsey Date: Wed, 31 Jul 2024 13:12:22 -0400 Subject: [PATCH 8/8] formatting --- rolling-update-kubernetes/src/main/resources/reference.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rolling-update-kubernetes/src/main/resources/reference.conf b/rolling-update-kubernetes/src/main/resources/reference.conf index dba70c99f..613b5a3de 100644 --- a/rolling-update-kubernetes/src/main/resources/reference.conf +++ b/rolling-update-kubernetes/src/main/resources/reference.conf @@ -35,7 +35,7 @@ akka.rollingupdate.kubernetes { pod-name = ${?KUBERNETES_POD_NAME} # Annotations to check to determine the revision. The default is suitable for "vanilla" - # Kubernetes Deployments, but other CI/CD systems may set a different annotation. + # Kubernetes Deployments, but other CI/CD systems may set a different annotation. revision-annotation = "deployment.kubernetes.io/revision" secure-api-server = true