2020 */
2121package eu.openanalytics.shinyproxyoperator
2222
23+ import eu.openanalytics.shinyproxyoperator.components.LabelFactory
2324import eu.openanalytics.shinyproxyoperator.controller.ShinyProxyEvent
2425import eu.openanalytics.shinyproxyoperator.controller.ShinyProxyEventType
2526import eu.openanalytics.shinyproxyoperator.helpers.IntegrationTestBase
@@ -36,6 +37,7 @@ import org.junit.jupiter.api.assertThrows
3637import kotlin.test.assertEquals
3738import kotlin.test.assertFalse
3839import kotlin.test.assertNotNull
40+ import kotlin.test.assertNull
3941import kotlin.test.assertTrue
4042
4143class MainIntegrationTest : IntegrationTestBase () {
@@ -904,4 +906,159 @@ class MainIntegrationTest : IntegrationTestBase() {
904906 spTestInstance.assertInstanceIsCorrect()
905907 job.cancel()
906908 }
909+
910+ @Test
911+ fun `operator should have correct antiAffinity defaults` () =
912+ setup(Mode .NAMESPACED ) { namespace, shinyProxyClient, namespacedClient, stableClient, operator , reconcileListener, _ ->
913+ // 1. create a SP instance
914+ val spTestInstance = ShinyProxyTestInstance (
915+ namespace,
916+ namespacedClient,
917+ shinyProxyClient,
918+ " simple_config.yaml" ,
919+ reconcileListener
920+ )
921+ val sp = spTestInstance.create()
922+
923+ val (resourceRetriever, shinyProxyLister) = operator .prepare()
924+
925+ // 3. start the operator and let it do it's work
926+ val job = GlobalScope .launch {
927+ operator .run (resourceRetriever, shinyProxyLister)
928+ }
929+
930+ // 4. wait until instance is created
931+ spTestInstance.waitForOneReconcile()
932+
933+ // 5. assert correctness
934+ spTestInstance.assertInstanceIsCorrect()
935+
936+ // 6. check antiAffinity rules
937+ val replicaSets = stableClient.inNamespace(namespace).apps().replicaSets().list().items
938+ assertEquals(1 , replicaSets.size)
939+ val replicaSet = replicaSets.firstOrNull { it.metadata.labels[LabelFactory .INSTANCE_LABEL ] == spTestInstance.hash }
940+ assertNotNull(replicaSet)
941+
942+ assertNotNull(replicaSet.spec.template.spec.affinity)
943+ assertNotNull(replicaSet.spec.template.spec.affinity.podAntiAffinity)
944+ assertNull(replicaSet.spec.template.spec.affinity.podAffinity)
945+ assertNull(replicaSet.spec.template.spec.affinity.nodeAffinity)
946+ assertEquals(0 , replicaSet.spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution.size)
947+ assertNotNull(replicaSet.spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution)
948+ assertEquals(1 , replicaSet.spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.size)
949+ val rule = replicaSet.spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0 ]
950+ assertEquals(1 , rule.weight)
951+ assertEquals(" kubernetes.io/hostname" , rule.podAffinityTerm.topologyKey)
952+ assertEquals(mapOf (
953+ LabelFactory .APP_LABEL to LabelFactory .APP_LABEL_VALUE ,
954+ LabelFactory .REALM_ID_LABEL to sp.realmId,
955+ LabelFactory .INSTANCE_LABEL to spTestInstance.hash
956+ ), rule.podAffinityTerm.labelSelector.matchLabels)
957+
958+ job.cancel()
959+ }
960+
961+ @Test
962+ fun `operator should have correct antiAffinity when required is true` () =
963+ setup(Mode .NAMESPACED ) { namespace, shinyProxyClient, namespacedClient, stableClient, operator , reconcileListener, _ ->
964+ // 1. create a SP instance
965+ val spTestInstance = ShinyProxyTestInstance (
966+ namespace,
967+ namespacedClient,
968+ shinyProxyClient,
969+ " affinity_required.yaml" ,
970+ reconcileListener
971+ )
972+ val sp = spTestInstance.create()
973+
974+ val (resourceRetriever, shinyProxyLister) = operator .prepare()
975+
976+ // 3. start the operator and let it do it's work
977+ val job = GlobalScope .launch {
978+ operator .run (resourceRetriever, shinyProxyLister)
979+ }
980+
981+ // 4. wait until instance is created
982+ spTestInstance.waitForOneReconcile()
983+
984+ // 5. assert correctness
985+ spTestInstance.assertInstanceIsCorrect()
986+
987+ // 6. check antiAffinity rules
988+ val replicaSets = stableClient.inNamespace(namespace).apps().replicaSets().list().items
989+ assertEquals(1 , replicaSets.size)
990+ val replicaSet = replicaSets.firstOrNull { it.metadata.labels[LabelFactory .INSTANCE_LABEL ] == spTestInstance.hash }
991+ assertNotNull(replicaSet)
992+
993+ assertNotNull(replicaSet.spec.template.spec.affinity)
994+ assertNotNull(replicaSet.spec.template.spec.affinity.podAntiAffinity)
995+ assertNull(replicaSet.spec.template.spec.affinity.podAffinity)
996+ assertNull(replicaSet.spec.template.spec.affinity.nodeAffinity)
997+ assertEquals(0 , replicaSet.spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.size)
998+ assertEquals(1 , replicaSet.spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution.size)
999+ assertNotNull(replicaSet.spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution)
1000+ val rule = replicaSet.spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0 ]
1001+ assertEquals(" kubernetes.io/hostname" , rule.topologyKey)
1002+ assertEquals(mapOf (
1003+ LabelFactory .APP_LABEL to LabelFactory .APP_LABEL_VALUE ,
1004+ LabelFactory .REALM_ID_LABEL to sp.realmId,
1005+ LabelFactory .INSTANCE_LABEL to spTestInstance.hash
1006+ ), rule.labelSelector.matchLabels)
1007+
1008+ job.cancel()
1009+ }
1010+
1011+
1012+ @Test
1013+ fun `operator should have correct antiAffinity when topologyKey is set` () =
1014+ setup(Mode .NAMESPACED ) { namespace, shinyProxyClient, namespacedClient, stableClient, operator , reconcileListener, _ ->
1015+ // 1. create a SP instance
1016+ val spTestInstance = ShinyProxyTestInstance (
1017+ namespace,
1018+ namespacedClient,
1019+ shinyProxyClient,
1020+ " affinity_toplogykey.yaml" ,
1021+ reconcileListener
1022+ )
1023+ val sp = spTestInstance.create()
1024+
1025+ val (resourceRetriever, shinyProxyLister) = operator .prepare()
1026+
1027+ // 3. start the operator and let it do it's work
1028+ val job = GlobalScope .launch {
1029+ operator .run (resourceRetriever, shinyProxyLister)
1030+ }
1031+
1032+ // 4. wait until instance is created
1033+ spTestInstance.waitForOneReconcile()
1034+
1035+ // 5. assert correctness
1036+ spTestInstance.assertInstanceIsCorrect()
1037+
1038+ // 6. check antiAffinity rules
1039+ val replicaSets = stableClient.inNamespace(namespace).apps().replicaSets().list().items
1040+ assertEquals(1 , replicaSets.size)
1041+ val replicaSet = replicaSets.firstOrNull { it.metadata.labels[LabelFactory .INSTANCE_LABEL ] == spTestInstance.hash }
1042+ assertNotNull(replicaSet)
1043+
1044+ assertNotNull(replicaSet.spec.template.spec.affinity)
1045+ assertNotNull(replicaSet.spec.template.spec.affinity.podAntiAffinity)
1046+ assertNull(replicaSet.spec.template.spec.affinity.podAffinity)
1047+ assertNull(replicaSet.spec.template.spec.affinity.nodeAffinity)
1048+ assertEquals(0 , replicaSet.spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution.size)
1049+ assertNotNull(replicaSet.spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution)
1050+ assertEquals(1 , replicaSet.spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.size)
1051+ val rule = replicaSet.spec.template.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0 ]
1052+ assertEquals(1 , rule.weight)
1053+ assertEquals(" example.com/custom-topology-key" , rule.podAffinityTerm.topologyKey)
1054+ assertEquals(mapOf (
1055+ LabelFactory .APP_LABEL to LabelFactory .APP_LABEL_VALUE ,
1056+ LabelFactory .REALM_ID_LABEL to sp.realmId,
1057+ LabelFactory .INSTANCE_LABEL to spTestInstance.hash
1058+ ), rule.podAffinityTerm.labelSelector.matchLabels)
1059+
1060+ job.cancel()
1061+ }
1062+
1063+
9071064}
0 commit comments