Skip to content

Commit

Permalink
Migrate integration tests to Scala 3
Browse files Browse the repository at this point in the history
  • Loading branch information
doriordan committed Oct 15, 2023
1 parent 6270609 commit a01a8bd
Show file tree
Hide file tree
Showing 21 changed files with 70 additions and 62 deletions.
13 changes: 6 additions & 7 deletions akka/src/it/scala/skuber/CustomResourceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import akka.stream.scaladsl._
import org.scalatest.matchers.should.Matchers
import org.scalatest.concurrent.Eventually
import play.api.libs.json._

import skuber.api.client.K8SException
import skuber.model.ResourceSpecification.{ScaleSubresource, Schema, Subresources}
import skuber.model.apiextensions.v1.CustomResourceDefinition
import skuber.model.{CustomResource, ListResource, ResourceDefinition, ResourceSpecification}
import skuber.model.{CustomResource, ListResource, ResourceDefinition, ResourceSpecification, Scale}


/**
Expand Down Expand Up @@ -95,7 +94,7 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
storage = true,
schema = Some(Schema(jsonSchema)), // schema is required since v1
subresources = Some(Subresources()
.withStatusSubresource // enable status subresource
.withStatusSubresource()// enable status subresource
.withScaleSubresource(ScaleSubresource(".spec.desiredReplicas", ".status.actualReplicas")) // enable scale subresource
)
)
Expand All @@ -113,7 +112,7 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
// This needs to be passed implicitly to the skuber API to enable it to process TestResource requests.
// The json paths in the Scale subresource must map to the replica fields in Spec and Status
// respectively above
implicit val testResourceDefinition = ResourceDefinition[TestResource](
implicit val testResourceDefinition: ResourceDefinition[TestResource] = ResourceDefinition[TestResource](
group = "test.skuber.io",
version = "v1alpha1",
kind = "SkuberTest",
Expand All @@ -123,8 +122,8 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {

// the following implicit values enable the scale and status methods on the skuber API to be called for this type
// (these calls will be rejected unless the subresources are enabled on the CRD)
implicit val statusSubEnabled=CustomResource.statusMethodsEnabler[TestResource]
implicit val scaleSubEnabled=CustomResource.scalingMethodsEnabler[TestResource]
implicit val statusSubEnabled: model.HasStatusSubresource[TestResource] =CustomResource.statusMethodsEnabler[TestResource]
implicit val scaleSubEnabled: Scale.SubresourceSpec[TestResource] =CustomResource.scalingMethodsEnabler[TestResource]

// Construct an exportable Kubernetes CRD that mirrors the details in the matching implicit resource definition above -
// the test will create it on Kubernetes so that the subsequent test requests can be handled by the cluster
Expand Down Expand Up @@ -228,7 +227,7 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
trackedEvents += event
}

def getCurrentResourceVersion: Future[String] = k8s.list[TestResourceList].map { l =>
def getCurrentResourceVersion: Future[String] = k8s.list[TestResourceList]().map { l =>
l.resourceVersion
}
def watchAndTrackEvents(sinceVersion: String) =
Expand Down
5 changes: 3 additions & 2 deletions akka/src/it/scala/skuber/DeploymentSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import org.scalatest.concurrent.{Eventually, ScalaFutures}
import skuber.model.{Container, LabelSelector, Pod}
import skuber.model.apps.v1.Deployment
import skuber.api.client.{DeleteOptions,DeletePropagation,K8SException}
import LabelSelector.dsl._

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success}

import scala.language.{postfixOps, reflectiveCalls}

class DeploymentSpec extends K8SFixture with Eventually with Matchers {
val nginxDeploymentName: String = java.util.UUID.randomUUID().toString

Expand All @@ -29,7 +32,6 @@ class DeploymentSpec extends K8SFixture with Eventually with Matchers {

it should "upgrade the newly created deployment" in { k8s =>
k8s.get[Deployment](nginxDeploymentName).flatMap { d =>
println(s"DEPLOYMENT TO UPDATE ==> $d")
val updatedDeployment = d.updateContainer(getNginxContainer("1.9.1"))
k8s.update(updatedDeployment).flatMap { _ =>
eventually(timeout(200.seconds), interval(5.seconds)) {
Expand Down Expand Up @@ -61,7 +63,6 @@ class DeploymentSpec extends K8SFixture with Eventually with Matchers {
def getNginxContainer(version: String): Container = Container(name = "nginx", image = "nginx:" + version).exposePort(80)

def getNginxDeployment(name: String, version: String): Deployment = {
import LabelSelector.dsl._
val nginxContainer = getNginxContainer(version)
val nginxTemplate = Pod.Template.Spec.named("nginx").addContainer(nginxContainer).addLabel("app" -> "nginx")
Deployment(name).withTemplate(nginxTemplate).withLabelSelector("app" is "nginx")
Expand Down
4 changes: 2 additions & 2 deletions akka/src/it/scala/skuber/ExecSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ class ExecSpec extends K8SFixture with Eventually with Matchers with BeforeAndAf
Await.result(k8s.create(getNginxPod(nginxPodName, "1.7.9")), 3.second)
// Let the pod running
Thread.sleep(3000)
k8s.close
k8s.close()
}

override def afterAll(): Unit = {
val k8s = k8sInit
Await.result(k8s.delete[Pod](nginxPodName), 3.second)
Thread.sleep(3000)
k8s.close
k8s.close()

super.afterAll()
}
Expand Down
5 changes: 4 additions & 1 deletion akka/src/it/scala/skuber/HorizontalPodAutoscalerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import skuber.model.autoscaling.v2.HorizontalPodAutoscaler
import skuber.model.autoscaling.v2.HorizontalPodAutoscaler.{ResourceMetricSource, UtilizationTarget}
import skuber.model.{Container, LabelSelector, Pod, Resource}
import skuber.model.apps.v1.Deployment
import LabelSelector.dsl._

import skuber.api.client._

import scala.language.{postfixOps, reflectiveCalls}

class HorizontalPodAutoscalerSpec extends K8SFixture with Eventually with Matchers {
behavior of "HorizontalPodAutoscalerV2"

Expand Down Expand Up @@ -85,7 +89,6 @@ class HorizontalPodAutoscalerSpec extends K8SFixture with Eventually with Matche
}

def getNginxDeployment(name: String, version: String): Deployment = {
import LabelSelector.dsl._
val nginxContainer = getNginxContainer(version)
val nginxTemplate = Pod.Template.Spec.named("nginx").addContainer(nginxContainer).addLabel("app" -> "nginx")
Deployment(name).withTemplate(nginxTemplate).withLabelSelector("app" is "nginx")
Expand Down
9 changes: 5 additions & 4 deletions akka/src/it/scala/skuber/K8SFixture.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import akka.actor.ActorSystem
import org.scalatest.FutureOutcome
import com.typesafe.config.ConfigFactory
import org.scalatest.flatspec.FixtureAsyncFlatSpec

import skuber.akkaclient._

import scala.concurrent.ExecutionContext

trait K8SFixture extends FixtureAsyncFlatSpec {

override type FixtureParam = AkkaKubernetesClient

implicit val system = ActorSystem()
implicit val dispatcher = system.dispatcher
implicit val system: ActorSystem = ActorSystem()
implicit val dispatcher: ExecutionContext = system.dispatcher

val config = ConfigFactory.load()

Expand All @@ -22,7 +23,7 @@ trait K8SFixture extends FixtureAsyncFlatSpec {
complete {
withFixture(test.toNoArgAsyncTest(k8s))
} lastly {
k8s.close
k8s.close()
}
}
}
4 changes: 2 additions & 2 deletions akka/src/it/scala/skuber/NamespaceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ class NamespaceSpec extends K8SFixture with Eventually with Matchers {
k8s.usingNamespace(namespace1Name).create(pod1)
.map { p =>
assert(p.name == nginxPodName1)
assert(p.namespace == namespace1Name)
assert(p.metadata.namespace == namespace1Name)
}
}

it should "honor namespace precedence hierarchy: object > client" in { k8s =>
k8s.usingNamespace(namespace1Name).create(pod2).map { p =>
assert(p.name == nginxPodName2)
assert(p.namespace == namespace2Name)
assert(p.metadata.namespace == namespace2Name)
}
}

Expand Down
4 changes: 2 additions & 2 deletions akka/src/it/scala/skuber/PatchSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ class PatchSpec extends K8SFixture with Eventually with Matchers with BeforeAndA
Await.result(k8s.create(getNginxPod(nginxPodName, "1.7.9")), 3.second)
// Let the pod running
Thread.sleep(3000)
k8s.close
k8s.close()
}

override def afterAll(): Unit = {
val k8s = k8sInit
Await.result(k8s.delete[Pod](nginxPodName), 3.second)
Thread.sleep(3000)
k8s.close
k8s.close()

super.afterAll()
}
Expand Down
10 changes: 5 additions & 5 deletions akka/src/it/scala/skuber/PodDisruptionBudgetSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import skuber.api.client.K8SException
import skuber.model.{Container, LabelSelector, Pod}
import skuber.model.apps.v1.Deployment
import skuber.model.policy.v1.PodDisruptionBudget
import LabelSelector.dsl._

import scala.language.{postfixOps, reflectiveCalls}

class PodDisruptionBudgetSpec extends K8SFixture with Eventually with Matchers {
behavior of "PodDisruptionBudget"

it should "create a PodDisruptionBudget" in { k8s =>
val name: String = java.util.UUID.randomUUID().toString
k8s.create(getNginxDeployment(name, "1.7.9")) flatMap { d =>
import LabelSelector.dsl._
k8s.create(getNginxDeployment(name, "1.7.9")) flatMap { _ =>
k8s.create(PodDisruptionBudget(name)
.withMinAvailable(Left(1))
.withLabelSelector("app" is "nginx")
Expand All @@ -26,8 +28,7 @@ class PodDisruptionBudgetSpec extends K8SFixture with Eventually with Matchers {

it should "update a PodDisruptionBudget" in { k8s =>
val name: String = java.util.UUID.randomUUID().toString
k8s.create(getNginxDeployment(name, "1.7.9")) flatMap { d =>
import LabelSelector.dsl._
k8s.create(getNginxDeployment(name, "1.7.9")) flatMap { _ =>
k8s.create(PodDisruptionBudget(name)
.withMinAvailable(Left(1))
.withLabelSelector("app" is "nginx")
Expand Down Expand Up @@ -65,7 +66,6 @@ class PodDisruptionBudgetSpec extends K8SFixture with Eventually with Matchers {
}

def getNginxDeployment(name: String, version: String): Deployment = {
import LabelSelector.dsl._
val nginxContainer = getNginxContainer(version)
val nginxTemplate = Pod.Template.Spec.named("nginx").addContainer(nginxContainer).addLabel("app" -> "nginx")
Deployment(name).withTemplate(nginxTemplate).withLabelSelector("app" is "nginx")
Expand Down
4 changes: 2 additions & 2 deletions akka/src/it/scala/skuber/PodLogSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ class PodLogSpec extends K8SFixture with Eventually with Matchers with BeforeAnd
Await.result(k8s.create(getNginxPod(podName, "1.7.9")), 3.second)
// Let the pod running
Thread.sleep(3000)
k8s.close
k8s.close()
}

override def afterAll(): Unit = {
val k8s = k8sInit(config)
Await.result(k8s.delete[Pod](podName), 3.second)
Thread.sleep(3000)
k8s.close
k8s.close()

super.afterAll()
}
Expand Down
3 changes: 2 additions & 1 deletion akka/src/it/scala/skuber/WatchContinuouslySpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class WatchContinuouslySpec extends K8SFixture with Eventually with Matchers wit
val deploymentOne = getNginxDeployment(deploymentOneName, "1.7.9")
val deploymentTwo = getNginxDeployment(deploymentTwoName, "1.7.9")

val stream = k8s.list[DeploymentList].map { l =>
val stream = k8s.list[DeploymentList]().map { l =>
k8s.watchAllContinuously[Deployment](Some(l.resourceVersion))
.viaMat(KillSwitches.single)(Keep.right)
.filter(event => event._object.name == deploymentOneName || event._object.name == deploymentTwoName)
Expand Down Expand Up @@ -175,6 +175,7 @@ class WatchContinuouslySpec extends K8SFixture with Eventually with Matchers wit

def getNginxDeployment(name: String, version: String): Deployment = {
import LabelSelector.dsl._
import scala.language.reflectiveCalls
val nginxContainer = getNginxContainer(version)
val nginxTemplate = Pod.Template.Spec.named("nginx").addContainer(nginxContainer).addLabel("app" -> "nginx")
Deployment(name).withTemplate(nginxTemplate).withLabelSelector("app" is "nginx")
Expand Down
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ val pekkoStreamTestkit = pekkoGroup %% "pekko-stream-testkit" % pekkoVersion
val pekkoActors = pekkoGroup %% "pekko-actor" % pekkoVersion

lazy val pekkoClientDependencies = Seq(pekkoActors, pekkoHttp, pekkoStream, pekkoSlf4j, logback, pekkoStreamTestkit,
scalaCheck % Test, specs2 % Test, mockito % Test, scalaTestMockito % Test, scalaTest % Test)
scalaCheck % Test, specs2 % Test, mockito % Test, scalaTestMockito % Test, scalaTest % "it, test")

lazy val pekko = (project in file("pekko"))
.configs(IntegrationTest)
Expand All @@ -106,7 +106,7 @@ val akkaBSLStreamTestKit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaBS
val akkaBSLActors = "com.typesafe.akka" %% "akka-actor" % akkaBSLVersion

lazy val akkaBSLClientDependencies = Seq(akkaBSLActors, akkaBSLHttp, akkaBSLStream, akkaBSLSlf4j, logback, akkaBSLStreamTestKit,
scalaCheck % Test, specs2 % Test, mockito % Test, scalaTestMockito % Test, scalaTest % Test)
scalaCheck % Test, specs2 % Test, mockito % Test, scalaTestMockito % Test, scalaTest % "it, test")

lazy val akka = (project in file("akka"))
.configs(IntegrationTest)
Expand Down
23 changes: 12 additions & 11 deletions pekko/src/it/scala/skuber/CustomResourceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import pekko.stream.scaladsl._
import org.scalatest.matchers.should.Matchers
import org.scalatest.concurrent.Eventually
import play.api.libs.json._

import skuber.api.client.K8SException
import skuber.model.ResourceSpecification.{ScaleSubresource, Schema, Subresources}
import skuber.model.apiextensions.v1.CustomResourceDefinition
import skuber.model.{CustomResource, ListResource, ResourceDefinition, ResourceSpecification}
import skuber.model.{CustomResource, ListResource, ResourceDefinition, ResourceSpecification, Scale}


/**
Expand Down Expand Up @@ -96,7 +95,7 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
storage = true,
schema = Some(Schema(jsonSchema)), // schema is required since v1
subresources = Some(Subresources()
.withStatusSubresource // enable status subresource
.withStatusSubresource() // enable status subresource
.withScaleSubresource(ScaleSubresource(".spec.desiredReplicas", ".status.actualReplicas")) // enable scale subresource
)
)
Expand All @@ -114,18 +113,18 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
// This needs to be passed implicitly to the skuber API to enable it to process TestResource requests.
// The json paths in the Scale subresource must map to the replica fields in Spec and Status
// respectively above
implicit val testResourceDefinition = ResourceDefinition[TestResource](
implicit val testResourceDefinition: ResourceDefinition[TestResource] = ResourceDefinition[TestResource](
group = "test.skuber.io",
version = "v1alpha1",
kind = "SkuberTest",
shortNames = List("test","tests"), // not needed, but handy if debugging the tests
shortNames = List("test", "tests"), // not needed, but handy if debugging the tests
versions = getVersions() // only needed for creating or updating the CRD, not needed if just manipulating custon resources
)

// the following implicit values enable the scale and status methods on the skuber API to be called for this type
// (these calls will be rejected unless the subresources are enabled on the CRD)
implicit val statusSubEnabled=CustomResource.statusMethodsEnabler[TestResource]
implicit val scaleSubEnabled=CustomResource.scalingMethodsEnabler[TestResource]
implicit val statusSubEnabled: model.HasStatusSubresource[TestResource] = CustomResource.statusMethodsEnabler[TestResource]
implicit val scaleSubEnabled: Scale.SubresourceSpec[TestResource] = CustomResource.scalingMethodsEnabler[TestResource]

// Construct an exportable Kubernetes CRD that mirrors the details in the matching implicit resource definition above -
// the test will create it on Kubernetes so that the subsequent test requests can be handled by the cluster
Expand Down Expand Up @@ -221,6 +220,8 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
import skuber.api.client.{EventType, WatchEvent}
import scala.collection.mutable.ListBuffer

import TestResource.testResourceDefinition

val testResourceName=java.util.UUID.randomUUID().toString
val testResource = TestResource(testResourceName, TestResource.Spec(1))

Expand All @@ -229,7 +230,7 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
trackedEvents += event
}

def getCurrentResourceVersion: Future[String] = k8s.list[TestResourceList].map { l =>
def getCurrentResourceVersion: Future[String] = k8s.list[TestResourceList]().map { l =>
l.resourceVersion
}
def watchAndTrackEvents(sinceVersion: String) =
Expand All @@ -243,7 +244,7 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
def createTestResource= k8s.create(testResource)
def deleteTestResource= k8s.delete[TestResource](testResourceName)

val killSwitchFut = for {
val killSwitchFut: Future[UniqueKillSwitch] = for {
currentTestResourceVersion <- getCurrentResourceVersion
(kill, _) <- watchAndTrackEvents(currentTestResourceVersion)
testResource <- createTestResource
Expand All @@ -253,8 +254,8 @@ class CustomResourceSpec extends K8SFixture with Eventually with Matchers {
eventually(timeout(200.seconds), interval(3.seconds)) {
trackedEvents.size shouldBe 2
trackedEvents(0)._type shouldBe EventType.ADDED
trackedEvents(0)._object.name shouldBe testResource.name
trackedEvents(0)._object.spec shouldBe testResource.spec
trackedEvents(0)._object.name should be(testResource.name)
assert(trackedEvents(0)._object.spec.desiredReplicas == testResource.spec.desiredReplicas)
trackedEvents(1)._type shouldBe EventType.DELETED
}

Expand Down
1 change: 1 addition & 0 deletions pekko/src/it/scala/skuber/DeploymentSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import skuber.api.client.{DeleteOptions,DeletePropagation,K8SException}
import scala.concurrent.duration._
import scala.concurrent.Await
import scala.util.{Failure, Success}
import scala.language.{postfixOps, reflectiveCalls}

class DeploymentSpec extends K8SFixture with Eventually with Matchers {
val nginxDeploymentName: String = java.util.UUID.randomUUID().toString
Expand Down
5 changes: 2 additions & 3 deletions pekko/src/it/scala/skuber/ExecSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import skuber.api.client.K8SException
import skuber.json.format._
import skuber.model.{Container, Pod}


import skuber.pekkoclient.k8sInit

class ExecSpec extends K8SFixture with Eventually with Matchers with BeforeAndAfterAll {
Expand All @@ -31,14 +30,14 @@ class ExecSpec extends K8SFixture with Eventually with Matchers with BeforeAndAf
Await.result(k8s.create(getNginxPod(nginxPodName, "1.7.9")), 3.second)
// Let the pod running
Thread.sleep(3000)
k8s.close
k8s.close()
}

override def afterAll(): Unit = {
val k8s = k8sInit
Await.result(k8s.delete[Pod](nginxPodName), 3.second)
Thread.sleep(3000)
k8s.close
k8s.close()

super.afterAll()
}
Expand Down
Loading

0 comments on commit a01a8bd

Please sign in to comment.