From 06eb7fb204a6f06a5c8f206f062842e5eaf4f3fd Mon Sep 17 00:00:00 2001 From: Tim Cuthbertson Date: Wed, 15 Nov 2023 18:27:50 +1100 Subject: [PATCH 1/3] bugfix: refresh before token expires, not after --- .../client/util/cache/AuthorizationCache.scala | 4 ++-- .../client/cache/AuthorizationCacheTest.scala | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala b/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala index dc560606..0d9a0913 100644 --- a/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala +++ b/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala @@ -38,8 +38,8 @@ object AuthorizationCache { case Some(cached) => F.realTimeInstant .flatMap { now => - val shouldRenew = - cached.expirationTimestamp.exists(_.isBefore(now.minusSeconds(refreshBeforeExpiration.toSeconds))) + val minExpiry = now.plusSeconds(refreshBeforeExpiration.toSeconds) + val shouldRenew = cached.expirationTimestamp.exists(_.isBefore(minExpiry)) if (shouldRenew) getAndCacheToken.flatMap { case Some(token) => token.pure[F] diff --git a/kubernetes-client/test/src/com/goyeau/kubernetes/client/cache/AuthorizationCacheTest.scala b/kubernetes-client/test/src/com/goyeau/kubernetes/client/cache/AuthorizationCacheTest.scala index f9d2f668..24941c7b 100644 --- a/kubernetes-client/test/src/com/goyeau/kubernetes/client/cache/AuthorizationCacheTest.scala +++ b/kubernetes-client/test/src/com/goyeau/kubernetes/client/cache/AuthorizationCacheTest.scala @@ -10,6 +10,7 @@ import org.http4s.{AuthScheme, Credentials} import org.http4s.headers.Authorization import cats.effect.unsafe.implicits.global import java.time.Instant +import scala.concurrent.duration.* class AuthorizationCacheTest extends FunSuite { @@ -73,6 +74,21 @@ class AuthorizationCacheTest extends FunSuite { io.unsafeRunSync() } + test(s"retrieve the token when it's going to expire within refreshBeforeExpiration") { + val io = for { + counter <- IO.ref(1) + auth = mkAuthorization( + expirationTimestamp = IO.realTimeInstant.map(_.plusSeconds(40).some), + token = counter.getAndUpdate(_ + 1).map(i => s"test-token-$i") + ) + cache <- AuthorizationCache[IO](retrieve = auth, refreshBeforeExpiration = 1.minute) + obtained <- (1 to 5).toList.traverse(i => cache.get.product(i.pure)) + } yield obtained.foreach { case (obtained, i) => + assertEquals(obtained, Authorization(Credentials.Token(AuthScheme.Bearer, s"test-token-$i"))) + } + io.unsafeRunSync() + } + test(s"fail if cannot retrieve the token when it's expired") { val io = for { counter <- IO.ref(1) From 597340c438453b9db076c2ae7fecf71361dd40c3 Mon Sep 17 00:00:00 2001 From: Tim Cuthbertson Date: Sat, 18 Nov 2023 10:52:13 +1100 Subject: [PATCH 2/3] use DurationConverters --- .../kubernetes/client/util/cache/AuthorizationCache.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala b/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala index 0d9a0913..68e72eca 100644 --- a/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala +++ b/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala @@ -5,6 +5,7 @@ import cats.effect.Async import cats.syntax.all.* import org.http4s.headers.Authorization import org.typelevel.log4cats.Logger +import scala.jdk.DurationConverters.* import scala.concurrent.duration.* @@ -38,7 +39,7 @@ object AuthorizationCache { case Some(cached) => F.realTimeInstant .flatMap { now => - val minExpiry = now.plusSeconds(refreshBeforeExpiration.toSeconds) + val minExpiry = now.plus(refreshBeforeExpiration.toJava) val shouldRenew = cached.expirationTimestamp.exists(_.isBefore(minExpiry)) if (shouldRenew) getAndCacheToken.flatMap { From a96cce767e0920047f3a056ca768d4195acb2fb7 Mon Sep 17 00:00:00 2001 From: Iurii Malchenko Date: Fri, 24 Nov 2023 13:55:47 +0100 Subject: [PATCH 3/3] add scala-java8-compat --- build.sc | 2 +- .../kubernetes/client/util/cache/AuthorizationCache.scala | 2 +- project/Dependencies.sc | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.sc b/build.sc index 2ec4e96f..c87ead84 100644 --- a/build.sc +++ b/build.sc @@ -35,7 +35,7 @@ class KubernetesClientModule(val crossScalaVersion: String) ) override def ivyDeps = - super.ivyDeps() ++ http4s ++ circe ++ circeYaml ++ bouncycastle ++ collectionCompat ++ logging + super.ivyDeps() ++ http4s ++ circe ++ circeYaml ++ bouncycastle ++ collectionCompat ++ logging ++ java8compat override def scalacPluginIvyDeps = super.scalacPluginIvyDeps() ++ (if (isScala3(scalaVersion())) Agg.empty else Agg(ivy"org.typelevel:::kind-projector:0.13.2")) diff --git a/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala b/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala index 68e72eca..c69c4f01 100644 --- a/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala +++ b/kubernetes-client/src/com/goyeau/kubernetes/client/util/cache/AuthorizationCache.scala @@ -5,7 +5,7 @@ import cats.effect.Async import cats.syntax.all.* import org.http4s.headers.Authorization import org.typelevel.log4cats.Logger -import scala.jdk.DurationConverters.* +import scala.compat.java8.DurationConverters.* import scala.concurrent.duration.* diff --git a/project/Dependencies.sc b/project/Dependencies.sc index c652e04f..347c3b0f 100644 --- a/project/Dependencies.sc +++ b/project/Dependencies.sc @@ -31,5 +31,7 @@ object Dependencies { lazy val logback = Agg(ivy"ch.qos.logback:logback-classic:1.4.11") + lazy val java8compat = Agg(ivy"org.scala-lang.modules::scala-java8-compat:1.0.2") + lazy val tests = Agg(ivy"org.scalameta::munit:0.7.29") }